diff --git a/types/gimloader/gimloader-tests.ts b/types/gimloader/gimloader-tests.ts index cef2a559ed2aee..ba3ca08edbb9d0 100644 --- a/types/gimloader/gimloader-tests.ts +++ b/types/gimloader/gimloader-tests.ts @@ -24,10 +24,10 @@ new GL(); // $ExpectType Api api.React; // $ExpectType typeof React api.UI; // $ExpectType Readonly api.hotkeys; // $ExpectType Readonly -api.libs; // $ExpectType Readonly +api.libs; // $ExpectType Readonly api.net; // $ExpectType Readonly api.patcher; // $ExpectType Readonly -api.plugins; // $ExpectType Readonly +api.plugins; // $ExpectType Readonly api.rewriter; // $ExpectType Readonly api.storage; // $ExpectType Readonly api.commands; // $ExpectType Readonly @@ -64,8 +64,6 @@ api.UI.showModal(document.createElement("div"), { }); api.requestReload(); -api.patcher.before({}, "foo", () => {}); -api.patcher.before({}, "foo", () => true); GL.net.gamemode; // $ExpectType string api.net.gamemode; // $ExpectType string api.net.onLoad((type, gamemode) => {}); @@ -80,6 +78,17 @@ api.rewriter.exposeVar("App", { multiple: false, }); +// Test patcher +let object = { a: true, b: (arg1: number, arg2: string) => true }; +api.patcher.after(object, "b", (thisVal, args, returnVal) => { + args[0]; // $ExpectType number + args[1]; // $ExpectType string + returnVal; // $ExpectType boolean +}); +// @ts-expect-error +api.patcher.after(object, "a", () => {}); + +// Test commands api.commands.addCommand({ text: "test", hidden: () => false, @@ -112,6 +121,7 @@ api.commands.addCommand({ api.commands.addCommand({ text: () => "something" }, () => {}); +// Test stores GL.stores.phaser; // $ExpectType PhaserStore window.stores.phaser; // $ExpectType PhaserStore let worldManagerInstance!: Gimloader.Stores.WorldManager; @@ -145,6 +155,13 @@ worldManager.physics.bodies.staticBodies; // $ExpectType Set worldManager.devices.interactives.findClosestInteractiveDevice([], 0, 0); // $ExpectType Device | undefined worldManager.inGameTerrainBuilder.clearPreviewLayer(); +// Test colyseus state +api.net.state.characters["..."].x; // $ExpectType number +api.net.state.characters.get("...")!.x; // $ExpectType number +api.net.state.teams[0].characters[0]; // $ExpectType string +api.net.state.mapSettings; // $ExpectType string + +// Test settings api.settings.something; api.settings.somethingElse; api.settings.something = 123; diff --git a/types/gimloader/index.d.ts b/types/gimloader/index.d.ts index 1c800cc6efadab..48e936754db3de 100644 --- a/types/gimloader/index.d.ts +++ b/types/gimloader/index.d.ts @@ -2110,7 +2110,7 @@ declare global { /** Should be a keyboardevent [code](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code) */ key?: string; /** Should be keyboardevent [codes](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code) */ - keys?: string[]; + keys?: ReadonlyArray; ctrl?: boolean; shift?: boolean; alt?: boolean; @@ -2260,6 +2260,193 @@ declare global { both?: () => void; error?: (error: any) => void; } + namespace Schema { + type ObjectSchema = T & { + listen( + key: K, + callback: (value: T[K], lastValue: T[K]) => void, + immediate?: boolean, + ): () => void; + onChange(callback: () => void): () => void; + }; + interface CollectionSchema { + onAdd(callback: (value: T, index: K) => void, immediate?: boolean): () => void; + onRemove(callback: (value: T, index: K) => void): () => void; + onChange(callback: (item: T, index: K) => void): () => void; + } + type MapSchema = + & { + [key: string]: T; + } + & Map + & CollectionSchema; + type ArraySchema = T[] & CollectionSchema; + interface AppearanceState { + skin: string; + tintModifierId: string; + trailId: string; + transparencyModifierId: string; + } + interface AssignmentState { + hasSavedProgress: boolean; + objective?: string; + percentageComplete?: number; + } + interface ClassDesignerState { + lastActivatedClassDeviceId: string; + lastClassDeviceActivationId: number; + } + interface HealthState { + classImmunityActive: boolean; + fragility: number; + lives: number; + maxHealth: number; + maxShield: number; + shield: number; + showHealthBar: boolean; + spawnImmunityActive: boolean; + } + interface InteractiveSlotState { + clipSize: number; + count: number; + currentClip: number; + durability: number; + itemId: string; + waiting: boolean; + waitingEndTime: number; + waitingStartTime: number; + } + interface InventoryState { + activeInteractiveSlot: number; + infiniteAmmo: boolean; + interactiveSlots: MapSchema; + interactiveSlotsOrder: ArraySchema; + } + interface PermissionsState { + adding: boolean; + editing: boolean; + manageCodeGrids: boolean; + removing: boolean; + } + interface PhysicsState { + isGrounded: boolean; + } + interface ProjectilesState { + aimAngle: number; + damageMultiplier: number; + } + interface XPState { + unredeemedXP: number; + } + interface ZoneAbilitiesOverridesState { + allowItemDrop: boolean; + allowResourceDrop: boolean; + allowWeaponDrop: boolean; + allowWeaponFire: boolean; + } + interface CharacterState { + appearance: ObjectSchema; + assignment: ObjectSchema; + classDesigner: ObjectSchema; + completedInitialPlacement: boolean; + health: ObjectSchema; + id: string; + inventory: ObjectSchema; + isActive: boolean; + isRespawning: boolean; + lastPlayersTeamId: string; + movementSpeed: number; + name: string; + openDeviceUI: string; + openDeviceUIChangeCounter: number; + permissions: ObjectSchema; + phase: boolean; + physics: ObjectSchema; + projectiles: ObjectSchema; + roleLevel: number; + scale: number; + score: number; + teamId: string; + teleportCount: number; + type: string; + x: number; + xp: ObjectSchema; + y: number; + zoneAbilitiesOverrides: ObjectSchema; + } + interface ActionCategoryState { + id: string; + name: string; + plural: string; + } + interface ActionItemState { + id: string; + category: string; + name: string; + url: string; + } + interface CallToActionState { + categories: ArraySchema; + items: ArraySchema; + } + interface GameSessionState { + callToAction: ObjectSchema; + countdownEnd: number; + phase: string; + resultsEnd: number; + } + interface SessionState { + allowGoogleTranslate: boolean; + cosmosBlocked: boolean; + gameOwnerId: string; + gameSession: ObjectSchema; + gameTime: number; + globalPermissions: ObjectSchema; + loadingPhase: boolean; + mapCreatorRoleLevel: number; + mapStyle: string; + modeType: string; + phase: string; + version: string; + } + interface DevicesState { + codeGrids: MapSchema; + } + interface WorldState { + devices: ObjectSchema; + height: number; + width: number; + } + interface CustomAssetState { + data: string; + icon: string; + id: string; + name: string; + optionId: string; + } + interface HooksState { + hookJSON: string; + } + interface MatchmakerState { + gameCode: string; + } + interface TeamState { + characters: ArraySchema; + id: string; + name: string; + score: number; + } + interface GimkitState { + characters: MapSchema; + customAssets: MapSchema; + hooks: ObjectSchema; + mapSettings: string; + matchmaker: ObjectSchema; + session: ObjectSchema; + teams: ArraySchema; + world: ObjectSchema; + } + } class BaseNetApi extends EventEmitter2 { constructor(); /** Which type of server the client is currently connected to */ @@ -2268,6 +2455,8 @@ declare global { get gamemode(): string; /** The room that the client is connected to, or null if there is no connection */ get room(): any; + /** Gimkit's internal Colyseus state */ + get state(): Schema.GimkitState; /** Whether the user is the one hosting the current game */ get isHost(): boolean; /** Sends a message to the server on a specific channel */ @@ -2282,7 +2471,7 @@ declare global { onLoad( id: string, callback: (type: ConnectionType, gamemode: string) => void, - gamemode?: string | string[], + gamemode?: string | ReadonlyArray, ): () => void; /** Cancels any calls to {@link onLoad} with the same id */ offLoad(id: string): void; @@ -2326,7 +2515,7 @@ declare global { */ onLoad( callback: (type: ConnectionType, gamemode: string) => void, - gamemode?: string | string[], + gamemode?: string | ReadonlyArray, ): () => void; /** Runs a callback when a request is made that matches a certain path (can have wildcards) */ modifyFetchRequest(path: string, callback: (options: RequesterOptions) => any): () => void; @@ -2346,7 +2535,7 @@ declare global { style?: string; className?: string; closeOnBackgroundClick?: boolean; - buttons?: ModalButton[]; + buttons?: ReadonlyArray; onClosed?: () => void; } type NoticeType = "info" | "success" | "error" | "warning" | "loading"; @@ -2741,30 +2930,56 @@ declare global { /** Adds a listener for when a stored value with a certain key changes */ onChange(key: string, callback: ValueChangeCallback): () => void; } + type BaseFunction = (...args: any[]) => any; + type FunctionKeys = keyof { + [K in keyof T as T[K] extends BaseFunction ? K : never]: T[K]; + }; - type PatcherAfterCallback = (thisVal: any, args: IArguments, returnVal: any) => any; + type PatcherAfterCallback = ( + thisVal: any, + args: T extends BaseFunction ? Parameters : any[], + returnVal: T extends BaseFunction ? ReturnType : any, + ) => any; - // eslint-disable-next-line @typescript-eslint/no-invalid-void-type - type PatcherBeforeCallback = (thisVal: any, args: IArguments) => boolean | void; + type PatcherBeforeCallback = ( + thisVal: any, + args: T extends BaseFunction ? Parameters : any[], + // eslint-disable-next-line @typescript-eslint/no-invalid-void-type + ) => boolean | void; - type PatcherInsteadCallback = (thisVal: any, args: IArguments) => void; + type PatcherInsteadCallback = (thisVal: any, args: T extends BaseFunction ? Parameters : any[]) => any; class PatcherApi { /** * Runs a callback after a function on an object has been run * @returns A function to remove the patch */ - after(id: string, object: any, method: string, callback: PatcherAfterCallback): () => void; + after>( + id: string, + object: O, + method: K, + callback: PatcherAfterCallback, + ): () => void; /** * Runs a callback before a function on an object has been run. * Return true from the callback to prevent the function from running * @returns A function to remove the patch */ - before(id: string, object: any, method: string, callback: PatcherBeforeCallback): () => void; + before>( + id: string, + object: O, + method: K, + callback: PatcherBeforeCallback, + ): () => void; /** * Runs a function instead of a function on an object * @returns A function to remove the patch */ - instead(id: string, object: any, method: string, callback: PatcherInsteadCallback): () => void; + instead>( + id: string, + object: O, + method: K, + callback: PatcherInsteadCallback, + ): () => void; /** Removes all patches with a given id */ unpatchAll(id: string): void; } @@ -2774,18 +2989,30 @@ declare global { * Runs a callback after a function on an object has been run * @returns A function to remove the patch */ - after(object: any, method: string, callback: PatcherAfterCallback): () => void; + after>( + object: O, + method: K, + callback: PatcherAfterCallback, + ): () => void; /** * Runs a callback before a function on an object has been run. * Return true from the callback to prevent the function from running * @returns A function to remove the patch */ - before(object: any, method: string, callback: PatcherBeforeCallback): () => void; + before>( + object: O, + method: K, + callback: PatcherBeforeCallback, + ): () => void; /** * Runs a function instead of a function on an object * @returns A function to remove the patch */ - instead(object: any, method: string, callback: PatcherInsteadCallback): () => void; + instead>( + object: O, + method: K, + callback: PatcherInsteadCallback, + ): () => void; } // eslint-disable-next-line @typescript-eslint/no-invalid-void-type @@ -2863,17 +3090,17 @@ declare global { interface CommandOptions { text: string | (() => string); - keywords?: string[]; + keywords?: ReadonlyArray; hidden?: () => boolean; } interface BaseCommandOptions { title: string; } interface CommandSelectOptions extends BaseCommandOptions { - options: { + options: ReadonlyArray<{ label: string; value: string; - }[]; + }>; } interface CommandNumberOptions extends BaseCommandOptions { min?: number; @@ -2930,6 +3157,11 @@ declare global { /** Gets the exported values of a library */ get(name: T): Gimloader.Libraries[T]; } + class ScopedLibsApi extends LibsApi { + constructor(id: string); + /** Gets a library by name, prompting the user to enable/download it if necessary. Returns a promise with its exports. */ + require(name: string, downloadUrl?: string): Promise; + } class PluginsApi { /** A list of all the plugins installed */ get list(): string[]; @@ -2947,48 +3179,117 @@ declare global { return: any; }; } + class ScopedPluginsApi extends PluginsApi { + constructor(id: string); + /** Gets a plugin by name, prompting the user to enable/download it if necessary. Returns a promise with its exports. */ + require(name: string, downloadUrl?: string): Promise; + } + interface SvelteExport { + Index: any; + Client: any; + Animate: any; + Attachments: any; + Easing: any; + Events: any; + Motion: any; + WindowReactivity: any; + Reactivity: any; + Store: any; + Transition: any; + } class Api { - /** - * @deprecated Gimkit has switched from Parcel to vite, rendering this api useless. - * @hidden - */ - static parcel: Readonly; /** Functions to edit Gimkit's code */ static rewriter: Readonly; + /** Functions to edit Gimkit's code */ + rewriter: Readonly; /** Functions to listen for key combinations */ static hotkeys: Readonly; + /** Functions to listen for key combinations */ + hotkeys: Readonly; /** * Ways to interact with the current connection to the server, * and functions to send general requests */ static net: Readonly; + /** + * Ways to interact with the current connection to the server, + * and functions to send general requests + */ + net: Readonly; /** Functions for interacting with the DOM */ static UI: Readonly; + /** Functions for interacting with the DOM */ + UI: Readonly; /** Functions for persisting data between reloads */ static storage: Readonly; + /** Functions for persisting data between reloads */ + storage: Readonly; /** Functions for intercepting the arguments and return values of functions */ static patcher: Readonly; + /** Functions for intercepting the arguments and return values of functions */ + patcher: Readonly; /** Functions for adding commands to the command palette */ static commands: Readonly; + /** Functions for adding commands to the command palette */ + commands: Readonly; /** Methods for getting info on libraries */ static libs: Readonly; + /** Methods for getting info on libraries */ + libs: Readonly; /** Gets the exported values of a library */ static lib: (name: T) => Gimloader.Libraries[T]; + /** Gets the exported values of a library */ + lib: (name: T) => Gimloader.Libraries[T]; /** Methods for getting info on plugins */ static plugins: Readonly; + /** Methods for getting info on plugins */ + plugins: Readonly; /** Gets the exported values of a plugin, if it has been enabled */ static plugin: (name: T) => Gimloader.Plugins[T]; + /** Gets the exported values of a plugin, if it has been enabled */ + plugin: (name: T) => Gimloader.Plugins[T]; /** Gimkit's internal react instance */ static get React(): typeof import("react"); + /** Gimkit's internal react instance */ + get React(): typeof import("react"); /** Gimkit's internal reactDom instance */ static get ReactDOM(): typeof import("react-dom/client"); + /** Gimkit's internal reactDom instance */ + get ReactDOM(): typeof import("react-dom/client"); /** A variety of Gimkit internal objects available in 2d gamemodes */ static get stores(): Stores.Stores; + /** A variety of gimkit internal objects available in 2d gamemodes */ + get stores(): Stores.Stores; + /** + * The exports of svelte v5.43.0, used internally by Gimloader and exposed to make scripts smaller. + * Should never be used by hand. + */ + static svelte_5_43_0: SvelteExport; + /** + * The exports of svelte v5.43.0, used internally by Gimloader and exposed to make scripts smaller. + * Should never be used by hand. + */ + svelte_5_43_0: SvelteExport; + /** + * @deprecated Gimkit has switched from Parcel to vite, rendering this api useless. + * @hidden + */ + static parcel: Readonly; + /** + * @deprecated Gimkit has switched from Parcel to vite, rendering this api useless. + * @hidden + */ + parcel: Readonly; /** * @deprecated Use GL.UI.notification * @hidden */ static get notification(): AntdNotification; + /** + * @deprecated Use api.UI.notification + * @hidden + */ + get notification(): AntdNotification; /** * @deprecated No longer supported * @hidden @@ -3018,49 +3319,8 @@ declare global { */ static get pluginManager(): Readonly; constructor(type?: string, name?: string); - /** - * @deprecated Gimkit has switched from Parcel to vite, rendering this api useless. - * @hidden - */ - parcel: Readonly; - /** Functions to edit Gimkit's code */ - rewriter: Readonly; - /** Functions to listen for key combinations */ - hotkeys: Readonly; - /** - * Ways to interact with the current connection to the server, - * and functions to send general requests - */ - net: Readonly; - /** Functions for interacting with the DOM */ - UI: Readonly; - /** Functions for persisting data between reloads */ - storage: Readonly; - /** Functions for intercepting the arguments and return values of functions */ - patcher: Readonly; - /** Functions for adding commands to the command palette */ - commands: Readonly; /** A utility for creating persistent settings menus, only available to plugins */ settings: PluginSettings; - /** Methods for getting info on libraries */ - libs: Readonly; - /** Gets the exported values of a library */ - lib: (name: T) => Gimloader.Libraries[T]; - /** Methods for getting info on plugins */ - plugins: Readonly; - /** Gets the exported values of a plugin, if it has been enabled */ - plugin: (name: T) => Gimloader.Plugins[T]; - /** Gimkit's internal react instance */ - get React(): typeof import("react"); - /** Gimkit's internal reactDom instance */ - get ReactDOM(): typeof import("react-dom/client"); - /** A variety of gimkit internal objects available in 2d gamemodes */ - get stores(): Stores.Stores; - /** - * @deprecated Use api.UI.notification - * @hidden - */ - get notification(): AntdNotification; /** Run a callback when the script is disabled */ onStop: (callback: () => void) => void; /**