@sculptr/sdk 0.0.0-stage → 2.17.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -2
- package/dist/content/index.d.ts +54 -0
- package/dist/decompiled-gml.d.ts +117 -0
- package/dist/host/index.d.ts +160 -0
- package/dist/image/index.d.ts +16 -0
- package/dist/index.d.ts +93 -0
- package/dist/index.js +663 -0
- package/dist/keyboard/index.d.ts +42 -0
- package/dist/resources/object.d.ts +109 -0
- package/dist/resources/script.d.ts +184 -0
- package/dist/resources/sprite.d.ts +142 -0
- package/dist/ui/index.d.ts +232 -0
- package/dist/utils.d.ts +4 -0
- package/package.json +47 -4
package/README.md
CHANGED
|
@@ -1,3 +1,24 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @sculptr/sdk
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
WIP
|
|
4
|
+
|
|
5
|
+
Write sculptr mods for GameMaker 8 and GameMaker Studio games.
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
npm install @sculptr/sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import { createMod } from "@sculptr/sdk";
|
|
13
|
+
|
|
14
|
+
export default createMod((mod) => {
|
|
15
|
+
mod.resource.object.create({
|
|
16
|
+
name: "greeter",
|
|
17
|
+
persistent: true,
|
|
18
|
+
events: {
|
|
19
|
+
create: ({ send }) => send("hello", "string(room)"),
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
mod.on("hello", (room) => console.log(`hello from ${room}`));
|
|
23
|
+
});
|
|
24
|
+
```
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { Block } from "../decompiled-gml";
|
|
2
|
+
import type { EventName } from "../host";
|
|
3
|
+
export interface ScriptContent {
|
|
4
|
+
readonly name: string;
|
|
5
|
+
readonly body: Block;
|
|
6
|
+
}
|
|
7
|
+
export interface ObjectContent {
|
|
8
|
+
readonly name: string;
|
|
9
|
+
/** The events the object declares itself, among the six a mod object can have. The same code is
|
|
10
|
+
* in `GameContent.events` under the engine's own name for the event. */
|
|
11
|
+
readonly events: Partial<Record<EventName, Block>>;
|
|
12
|
+
}
|
|
13
|
+
/** One piece of the game's code, named so a mod can say which one it means. */
|
|
14
|
+
export interface CodeContent {
|
|
15
|
+
/**
|
|
16
|
+
* How the engine names this piece of code -- `world.KeyPress_82`, `player.Collision_17`,
|
|
17
|
+
* `boss.Alarm_0` on GameMaker 8. Engine-specific on purpose: a name the engine itself uses is
|
|
18
|
+
* one you can find again in the IDE.
|
|
19
|
+
*
|
|
20
|
+
* For room code (`RoomCodeContent`) it is `<room>.room` or `<room>.instance_<id>`.
|
|
21
|
+
*/
|
|
22
|
+
readonly name: string;
|
|
23
|
+
readonly body: Block;
|
|
24
|
+
}
|
|
25
|
+
/** one piece of code a room runs when it loads */
|
|
26
|
+
export interface RoomCodeContent extends CodeContent {
|
|
27
|
+
/** the room whose load runs this */
|
|
28
|
+
readonly room: string;
|
|
29
|
+
/** the object of the instance this is the creation code of */
|
|
30
|
+
readonly object: string | null;
|
|
31
|
+
}
|
|
32
|
+
/** Game sound asset */
|
|
33
|
+
export interface SoundContent {
|
|
34
|
+
readonly name: string;
|
|
35
|
+
/** Whether playing this sound stops whatever else was playing. */
|
|
36
|
+
readonly exclusive: boolean;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Game resources. Lossy. Useful for detecting patterns.
|
|
40
|
+
*/
|
|
41
|
+
export interface GameContent {
|
|
42
|
+
readonly scripts: readonly ScriptContent[];
|
|
43
|
+
readonly objects: readonly ObjectContent[];
|
|
44
|
+
/** every event every object declares, flat, as addressable code */
|
|
45
|
+
readonly events: readonly CodeContent[];
|
|
46
|
+
/** the game's sound assets */
|
|
47
|
+
readonly sounds: readonly SoundContent[];
|
|
48
|
+
/** a room's own creation code, and the creation code of each instance placed in it */
|
|
49
|
+
readonly rooms: readonly RoomCodeContent[];
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* The highest constant argument index a piece of the game's code reads, or -1 for none.
|
|
53
|
+
*/
|
|
54
|
+
export declare const highestArgument: (block: Block) => number;
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for representing decompiled GML code.
|
|
3
|
+
* Useful for detecting patterns in a game (e.g. identify the "killPlayer" script, etc.)
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* A GML block (list of statements), lossy.
|
|
7
|
+
*/
|
|
8
|
+
export type Block = Stmt[];
|
|
9
|
+
/**
|
|
10
|
+
* Where a statement is, opaquely. Only good for `mod.resource.script.insert`, and only for the game
|
|
11
|
+
* and launch it came from, so never persist one.
|
|
12
|
+
*/
|
|
13
|
+
export type At = string & {
|
|
14
|
+
readonly __at: unique symbol;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* A GML statement, lossy.
|
|
18
|
+
*
|
|
19
|
+
* `at` is absent when the engine could not place the statement (a `for` header's parts, a
|
|
20
|
+
* decompiler's temporary); inserting at one is refused.
|
|
21
|
+
*/
|
|
22
|
+
export type Stmt = {
|
|
23
|
+
k: "assign";
|
|
24
|
+
at?: At;
|
|
25
|
+
target: Expr;
|
|
26
|
+
op: "=" | "+=" | "-=" | "*=" | "/=" | "other";
|
|
27
|
+
value: Expr;
|
|
28
|
+
} | {
|
|
29
|
+
k: "call";
|
|
30
|
+
at?: At;
|
|
31
|
+
call: CallExpr;
|
|
32
|
+
} | {
|
|
33
|
+
k: "if";
|
|
34
|
+
at?: At;
|
|
35
|
+
cond: Expr;
|
|
36
|
+
then: Block;
|
|
37
|
+
else: Block;
|
|
38
|
+
} | {
|
|
39
|
+
k: "with";
|
|
40
|
+
at?: At;
|
|
41
|
+
target: Expr;
|
|
42
|
+
body: Block;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Any loop
|
|
46
|
+
*/
|
|
47
|
+
| {
|
|
48
|
+
k: "loop";
|
|
49
|
+
at?: At;
|
|
50
|
+
body: Block;
|
|
51
|
+
} | {
|
|
52
|
+
k: "switch";
|
|
53
|
+
at?: At;
|
|
54
|
+
value: Expr;
|
|
55
|
+
bodies: Block[];
|
|
56
|
+
} | {
|
|
57
|
+
k: "exit";
|
|
58
|
+
at?: At;
|
|
59
|
+
value: Expr | null;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Anything not modelled here: `break`, `continue`, a `case` label.
|
|
63
|
+
*/
|
|
64
|
+
| {
|
|
65
|
+
k: "unknown";
|
|
66
|
+
at?: At;
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Every statement in a block, in source order, descending into branches, bodies and cases:
|
|
70
|
+
* ```ts
|
|
71
|
+
* for (const stmt of walk(script.body)) {
|
|
72
|
+
* if (stmt.k === "call" && stmt.call.name === "instance_destroy") ...
|
|
73
|
+
* }
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
export declare function walk(block: Block): Generator<Stmt>;
|
|
77
|
+
export type Expr = {
|
|
78
|
+
k: "number";
|
|
79
|
+
value: number;
|
|
80
|
+
} | {
|
|
81
|
+
k: "string";
|
|
82
|
+
value: string;
|
|
83
|
+
} | {
|
|
84
|
+
k: "constant";
|
|
85
|
+
name: string;
|
|
86
|
+
} | {
|
|
87
|
+
k: "asset";
|
|
88
|
+
kind: "object" | "script" | "sprite" | "room" | "sound" | "other";
|
|
89
|
+
name: string;
|
|
90
|
+
} | {
|
|
91
|
+
k: "var";
|
|
92
|
+
scope: "local" | "self" | "global" | "builtin";
|
|
93
|
+
name: string;
|
|
94
|
+
} | {
|
|
95
|
+
k: "field";
|
|
96
|
+
of: Expr;
|
|
97
|
+
name: string;
|
|
98
|
+
} | {
|
|
99
|
+
k: "index";
|
|
100
|
+
of: Expr;
|
|
101
|
+
at: Expr[];
|
|
102
|
+
} | {
|
|
103
|
+
k: "arg";
|
|
104
|
+
index: number | null;
|
|
105
|
+
} | CallExpr | {
|
|
106
|
+
k: "op";
|
|
107
|
+
op: string;
|
|
108
|
+
args: Expr[];
|
|
109
|
+
} | {
|
|
110
|
+
k: "unknown";
|
|
111
|
+
};
|
|
112
|
+
export interface CallExpr {
|
|
113
|
+
k: "call";
|
|
114
|
+
kind: "script" | "builtin";
|
|
115
|
+
name: string;
|
|
116
|
+
args: Expr[];
|
|
117
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import type { Block } from "../decompiled-gml";
|
|
2
|
+
import type { ModUi } from "../ui";
|
|
3
|
+
/**
|
|
4
|
+
* GameMaker version
|
|
5
|
+
*
|
|
6
|
+
* 8.1 and 8.2 are treated as gm8.
|
|
7
|
+
* Studio 1.4 and 2.x are treated as gms.
|
|
8
|
+
*/
|
|
9
|
+
export type Engine = "gm8" | "gms";
|
|
10
|
+
/**
|
|
11
|
+
* The host's language
|
|
12
|
+
*/
|
|
13
|
+
export type Language = "en" | "zh-CN" | "ja" | "ko" | "es" | "pt-BR" | "de" | "fr" | "it" | "ru" | "pl";
|
|
14
|
+
/**
|
|
15
|
+
* The object events accessible to a mod.
|
|
16
|
+
*/
|
|
17
|
+
export type EventName = "create" | "destroy" | "beginStep" | "step" | "endStep" | "draw";
|
|
18
|
+
export interface Identity {
|
|
19
|
+
/**
|
|
20
|
+
* Unique across all mods. All mangled names are derived from it.
|
|
21
|
+
*/
|
|
22
|
+
id: string;
|
|
23
|
+
version: string;
|
|
24
|
+
}
|
|
25
|
+
interface HostObject {
|
|
26
|
+
kind: "object";
|
|
27
|
+
name: string;
|
|
28
|
+
events: Partial<Record<EventName, string>>;
|
|
29
|
+
depth?: number;
|
|
30
|
+
persistent?: boolean;
|
|
31
|
+
visible?: boolean;
|
|
32
|
+
}
|
|
33
|
+
interface HostScript {
|
|
34
|
+
kind: "script";
|
|
35
|
+
name: string;
|
|
36
|
+
source: string;
|
|
37
|
+
}
|
|
38
|
+
interface HostHook {
|
|
39
|
+
kind: "hook";
|
|
40
|
+
script: string;
|
|
41
|
+
original: string;
|
|
42
|
+
source: string;
|
|
43
|
+
}
|
|
44
|
+
interface HostInsert {
|
|
45
|
+
kind: "insert";
|
|
46
|
+
/** The statement's opaque token, from `mod.content`. */
|
|
47
|
+
at: string;
|
|
48
|
+
place: "before" | "after" | "instead";
|
|
49
|
+
/** The asset name of a script declared alongside this. */
|
|
50
|
+
call: string;
|
|
51
|
+
}
|
|
52
|
+
interface HostGameCode {
|
|
53
|
+
scripts: {
|
|
54
|
+
name: string;
|
|
55
|
+
body: Block;
|
|
56
|
+
}[];
|
|
57
|
+
objects: {
|
|
58
|
+
name: string;
|
|
59
|
+
events: Partial<Record<EventName, Block>>;
|
|
60
|
+
}[];
|
|
61
|
+
events: {
|
|
62
|
+
name: string;
|
|
63
|
+
body: Block;
|
|
64
|
+
}[];
|
|
65
|
+
sounds: {
|
|
66
|
+
name: string;
|
|
67
|
+
exclusive: boolean;
|
|
68
|
+
}[];
|
|
69
|
+
rooms: {
|
|
70
|
+
name: string;
|
|
71
|
+
body: Block;
|
|
72
|
+
room: string;
|
|
73
|
+
object: string | null;
|
|
74
|
+
}[];
|
|
75
|
+
}
|
|
76
|
+
interface HostGml {
|
|
77
|
+
send(expression: string): string;
|
|
78
|
+
receive(variable: string): string;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* The raw API exposed to a mod. You shouldn't need to use this directly.
|
|
82
|
+
*/
|
|
83
|
+
/**
|
|
84
|
+
* A chosen character. `sheet` is a 128x128 PNG: four 32x32 frames across, four rows down --
|
|
85
|
+
* idle, run, jump, fall, each row repeating its last frame if its animation is shorter.
|
|
86
|
+
*
|
|
87
|
+
* The bytes rather than a URL, so a mod needs no network -- and so it works in the main process,
|
|
88
|
+
* which cannot fetch the app's own scheme.
|
|
89
|
+
*/
|
|
90
|
+
export interface HostSkin {
|
|
91
|
+
readonly id: string;
|
|
92
|
+
readonly sheet: Uint8Array;
|
|
93
|
+
}
|
|
94
|
+
export type ControlAction = "up" | "down" | "left" | "right" | "confirm" | "cancel" | "retry";
|
|
95
|
+
export declare const CANONICAL_CONTROL_KEYS: Readonly<Record<ControlAction, string>>;
|
|
96
|
+
/** Every action, in the order the host shows them. */
|
|
97
|
+
export declare const CONTROL_ACTIONS: readonly ControlAction[];
|
|
98
|
+
/**
|
|
99
|
+
* What the player bound each action to
|
|
100
|
+
*/
|
|
101
|
+
export type HostControls = Readonly<Record<ControlAction, readonly string[]>>;
|
|
102
|
+
/**
|
|
103
|
+
* Whether a binding is a controller input rather than a key.
|
|
104
|
+
*
|
|
105
|
+
* Controller bindings live in the same list as keys (`PadButton0`, `PadAxis1Plus`, ... -- the
|
|
106
|
+
* Gamepad API's standard-mapping indices). `gameMakerKey` answers `0` for them, so a mod that only
|
|
107
|
+
* deals in keys ignores them for free.
|
|
108
|
+
*/
|
|
109
|
+
export declare function isPadBinding(code: string): boolean;
|
|
110
|
+
/** Who is playing. */
|
|
111
|
+
export interface HostPlayer {
|
|
112
|
+
readonly account: {
|
|
113
|
+
readonly id: string;
|
|
114
|
+
readonly name: string;
|
|
115
|
+
} | null;
|
|
116
|
+
readonly skin: HostSkin | null;
|
|
117
|
+
readonly room: HostRoom | null;
|
|
118
|
+
readonly language: Language;
|
|
119
|
+
readonly controls: HostControls;
|
|
120
|
+
}
|
|
121
|
+
export interface HostRoom {
|
|
122
|
+
readonly id: string;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Handing bytes to the game as a file.
|
|
126
|
+
*
|
|
127
|
+
* The host always owns the filesystem the game reads: in the browser both engines share one
|
|
128
|
+
* virtual filesystem that lives in the app, and a native install is a real game reading real files
|
|
129
|
+
* the app put there. So a picture is written, not transmitted.
|
|
130
|
+
*/
|
|
131
|
+
export interface HostFiles {
|
|
132
|
+
/**
|
|
133
|
+
* Writes the bytes and answers with the path the *game* should open.
|
|
134
|
+
*
|
|
135
|
+
* `at` is the directory the game reported: the string it puts in front of a filename. A host
|
|
136
|
+
* whose filesystem is the game's own composes the path from it, so both sides mean the same file
|
|
137
|
+
* without anyone guessing how that engine resolves a relative name. A host writing a real file
|
|
138
|
+
* somewhere of its own choosing ignores it.
|
|
139
|
+
*/
|
|
140
|
+
write(name: string, bytes: Uint8Array, at: string): Promise<string>;
|
|
141
|
+
}
|
|
142
|
+
export interface HostApi {
|
|
143
|
+
readonly identity: Identity;
|
|
144
|
+
readonly target: {
|
|
145
|
+
engine: Engine;
|
|
146
|
+
};
|
|
147
|
+
readonly game: HostGameCode;
|
|
148
|
+
getPlayer(): HostPlayer;
|
|
149
|
+
resource: {
|
|
150
|
+
create(resource: HostObject | HostScript | HostHook | HostInsert): void;
|
|
151
|
+
};
|
|
152
|
+
readonly gml: HostGml;
|
|
153
|
+
readonly files: HostFiles;
|
|
154
|
+
send(message: string): void;
|
|
155
|
+
readonly ui: ModUi;
|
|
156
|
+
on(event: "message", handler: (message: string) => void): void;
|
|
157
|
+
on(event: "start", handler: () => void): void;
|
|
158
|
+
on(event: "player", handler: (player: HostPlayer) => void): void;
|
|
159
|
+
}
|
|
160
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface ImageSize {
|
|
2
|
+
width: number;
|
|
3
|
+
height: number;
|
|
4
|
+
}
|
|
5
|
+
export interface ImageRect extends ImageSize {
|
|
6
|
+
x: number;
|
|
7
|
+
y: number;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* A PNG's dimensions, read from its header -- so no decoder, in either host.
|
|
11
|
+
*/
|
|
12
|
+
export declare const pngSize: (png: Uint8Array) => ImageSize;
|
|
13
|
+
/**
|
|
14
|
+
* One rectangle of a picture, as its own PNG.
|
|
15
|
+
*/
|
|
16
|
+
export declare const sliceImage: (png: Uint8Array, rect: ImageRect) => Promise<Uint8Array>;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import type { GameContent } from "./content";
|
|
2
|
+
import type { Engine, HostApi, HostPlayer } from "./host";
|
|
3
|
+
import { type ObjectActions } from "./resources/object";
|
|
4
|
+
import { type ScriptActions } from "./resources/script";
|
|
5
|
+
import { type SpriteActions } from "./resources/sprite";
|
|
6
|
+
import type { ModUi } from "./ui";
|
|
7
|
+
import { type EventHandler } from "./utils";
|
|
8
|
+
export type { ControlAction, Engine, EventName, HostApi, HostControls, HostPlayer, HostRoom, HostSkin, Identity, Language, } from "./host";
|
|
9
|
+
export { CANONICAL_CONTROL_KEYS, CONTROL_ACTIONS, isPadBinding } from "./host";
|
|
10
|
+
export type { ImageRect, ImageSize } from "./image";
|
|
11
|
+
export { pngSize, sliceImage } from "./image";
|
|
12
|
+
export type { CodeContent, GameContent, ObjectContent, RoomCodeContent, ScriptContent, SoundContent, } from "./content";
|
|
13
|
+
export { highestArgument } from "./content";
|
|
14
|
+
export type { At, Block, CallExpr, Expr, Stmt } from "./decompiled-gml";
|
|
15
|
+
export { walk } from "./decompiled-gml";
|
|
16
|
+
export type { ObjectContext, ObjectGml, ObjectReceiveContext, ObjectReceiveGml, ObjectSpec, ObjectVars, } from "./resources/object";
|
|
17
|
+
export type { HookContext, HookWrap, InsertContext, InsertSpec, OriginalScript, ScriptContext, ScriptSpec, } from "./resources/script";
|
|
18
|
+
export type { Sprite, SpriteOptions, SpriteSize, SpriteSource } from "./resources/sprite";
|
|
19
|
+
export type { EventHandler } from "./utils";
|
|
20
|
+
export { gameMakerKey } from "./keyboard";
|
|
21
|
+
export type { Bindable, ModUi, ReadonlyRef, Ref, UiAlign, UiBuilder, UiButtonOptions, UiColOptions, UiEachOptions, UiGap, UiInputOptions, UiKeybindOptions, UiNodeSpec, UiRowOptions, UiScrollOptions, UiSectionOptions, UiSelectOption, UiSelectOptions, UiSpec, UiStateOptions, UiTextOptions, UiToggleOptions, UiTone, UiVariant, } from "./ui";
|
|
22
|
+
export interface Mod {
|
|
23
|
+
engine: Engine;
|
|
24
|
+
/**
|
|
25
|
+
* Who is playing, the character they chose, and the language the host is in. The first two are
|
|
26
|
+
* null when signed out; `skin` is also null when they never picked one, and `language` is always
|
|
27
|
+
* set.
|
|
28
|
+
*
|
|
29
|
+
* A function because it can change while the game runs, so read it again rather than keeping the
|
|
30
|
+
* result. During the mod's setup it is pinned -- on a native install that setup runs twice, once
|
|
31
|
+
* to bake the GML and once to run this JavaScript, and a mod whose resources depended on a live
|
|
32
|
+
* value could declare two different things.
|
|
33
|
+
*/
|
|
34
|
+
getPlayer: () => HostPlayer;
|
|
35
|
+
/**
|
|
36
|
+
* The player signed in or out, picked a different character, or changed the host's language.
|
|
37
|
+
* Never during setup, so what a mod declares cannot depend on it -- only what it does with what
|
|
38
|
+
* it declared.
|
|
39
|
+
*/
|
|
40
|
+
onPlayerChange(handler: (player: HostPlayer) => void): void;
|
|
41
|
+
/**
|
|
42
|
+
* Existing game content. Useful for detecting patterns.
|
|
43
|
+
*/
|
|
44
|
+
content: GameContent;
|
|
45
|
+
/**
|
|
46
|
+
* Manipulate the game resources.
|
|
47
|
+
*/
|
|
48
|
+
resource: {
|
|
49
|
+
object: ObjectActions;
|
|
50
|
+
script: ScriptActions;
|
|
51
|
+
sprite: SpriteActions;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* A path for a scratch file as a GML expression.
|
|
55
|
+
* Not deleted automatically, so delete it once you're done.
|
|
56
|
+
*/
|
|
57
|
+
scratchPath(name: string): string;
|
|
58
|
+
/**
|
|
59
|
+
* A call to one of this mod's own scripts, as GML.
|
|
60
|
+
*
|
|
61
|
+
* The same thing an event's context hands you, available without one -- which is what lets a
|
|
62
|
+
* library built on top of this declare scripts and then write calls to them without every one of
|
|
63
|
+
* its functions taking a context it does not otherwise need.
|
|
64
|
+
*/
|
|
65
|
+
call(script: string, ...args: string[]): string;
|
|
66
|
+
/**
|
|
67
|
+
* Called once the game is running and can hear this mod.
|
|
68
|
+
*/
|
|
69
|
+
onStart(handler: () => void): void;
|
|
70
|
+
/**
|
|
71
|
+
* Receive an event from GML to JS.
|
|
72
|
+
*/
|
|
73
|
+
on(event: string, handler: EventHandler): void;
|
|
74
|
+
/**
|
|
75
|
+
* Send an event from JS to GML.
|
|
76
|
+
*/
|
|
77
|
+
send(event: string, payload?: string): void;
|
|
78
|
+
/**
|
|
79
|
+
* This mod's own panel, shown beside the game while it runs.
|
|
80
|
+
*
|
|
81
|
+
* Where a mod's settings live. Rather than the host growing a checkbox for every mod that needs
|
|
82
|
+
* one -- which it cannot do at all for a mod it does not ship -- the mod brings its own UI and the
|
|
83
|
+
* app renders it without knowing what any of it means. See `ModUi`.
|
|
84
|
+
*/
|
|
85
|
+
ui: ModUi;
|
|
86
|
+
}
|
|
87
|
+
export interface ModDefinition {
|
|
88
|
+
activate: (api: HostApi) => void;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Entry point for creating a mod
|
|
92
|
+
*/
|
|
93
|
+
export declare const createMod: (init: (mod: Mod) => void) => ModDefinition;
|