@mudlet/mudlet-web 0.3.0 → 0.4.0
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/LICENSE +338 -338
- package/README.md +158 -150
- package/dist-lib/assets/qt-resources/index.d.ts +16 -0
- package/dist-lib/branding.d.ts +1 -1
- package/dist-lib/hooks/useMudSession.d.ts +1 -1
- package/dist-lib/hooks/useOutput.d.ts +3 -1
- package/dist-lib/import/defaultPackages.d.ts +35 -2
- package/dist-lib/import/defaults/generic_mapper/generic_mapper.mpackage +0 -0
- package/dist-lib/import/defaults/gui-drop/gui-drop.mpackage +0 -0
- package/dist-lib/import/defaults/{run-lua-code.mpackage → mudlet-base-ui/mudlet-base-ui.mpackage} +0 -0
- package/dist-lib/import/defaults/mudlet-mapper.xml +13023 -13023
- package/dist-lib/import/defaults/run-lua-code/run-lua-code.mpackage +0 -0
- package/dist-lib/import/packageExport.d.ts +71 -0
- package/dist-lib/import/packageInstaller.d.ts +4 -1
- package/dist-lib/index.js +45910 -39931
- package/dist-lib/logging/SessionLogger.d.ts +66 -1
- package/dist-lib/map/MapStore.d.ts +32 -4
- package/dist-lib/map/mapImageExport.d.ts +1 -1
- package/dist-lib/map/mapZoom.d.ts +71 -0
- package/dist-lib/mud/ItemIdSequence.d.ts +23 -0
- package/dist-lib/mud/MudSession.d.ts +113 -11
- package/dist-lib/mud/PatternEngine.d.ts +6 -1
- package/dist-lib/mud/commandSplit.d.ts +16 -0
- package/dist-lib/mud/connection/LineAssembler.d.ts +56 -0
- package/dist-lib/mud/connection/MudClient.d.ts +136 -19
- package/dist-lib/mud/connection/TelnetNegotiator.d.ts +39 -0
- package/dist-lib/mud/connection/telnetByteTags.d.ts +35 -0
- package/dist-lib/mud/events.d.ts +86 -4
- package/dist-lib/mud/games/bundledGames.d.ts +29 -0
- package/dist-lib/mud/games/gameIcons.d.ts +5 -0
- package/dist-lib/mud/keybindings/KeyEngine.d.ts +9 -2
- package/dist-lib/mud/keybindings/browserReservedKeys.d.ts +5 -1
- package/dist-lib/mud/keybindings/keyEventTarget.d.ts +17 -0
- package/dist-lib/mud/keybindings/qtKeys.d.ts +2 -0
- package/dist-lib/mud/protocol/charLoginFlow.d.ts +68 -0
- package/dist-lib/mud/protocol/charset.d.ts +27 -5
- package/dist-lib/mud/protocol/constants.d.ts +1 -0
- package/dist-lib/mud/protocol/gmcp.d.ts +19 -3
- package/dist-lib/mud/protocol/index.d.ts +1 -1
- package/dist-lib/mud/protocol/msspTls.d.ts +54 -0
- package/dist-lib/mud/protocol/mxp.d.ts +28 -5
- package/dist-lib/mud/protocol/tlsCodes.d.ts +4 -0
- package/dist-lib/mud/replay/ReplayPlayer.d.ts +17 -0
- package/dist-lib/mud/text/Console.d.ts +64 -0
- package/dist-lib/mud/text/FormatState.d.ts +66 -3
- package/dist-lib/mud/text/hyperlinkVisibility.d.ts +35 -0
- package/dist-lib/mud/text/osc8Docs.d.ts +23 -0
- package/dist-lib/mud/text/serverWrap.d.ts +191 -0
- package/dist-lib/mud/timers/TimerEngine.d.ts +43 -12
- package/dist-lib/mud/triggers/TriggerEngine.d.ts +112 -3
- package/dist-lib/scripting/EngineHost.d.ts +56 -3
- package/dist-lib/scripting/IScriptingRuntime.d.ts +22 -0
- package/dist-lib/scripting/MxpFrameManager.d.ts +118 -0
- package/dist-lib/scripting/ScriptingAPI.d.ts +331 -54
- package/dist-lib/scripting/ScriptingEngine.d.ts +181 -24
- package/dist-lib/scripting/http/HttpService.d.ts +51 -1
- package/dist-lib/scripting/lua/LuaRuntime.d.ts +159 -2
- package/dist-lib/scripting/lua/bindings/map.d.ts +0 -12
- package/dist-lib/scripting/lua/utf8Patterns.d.ts +59 -0
- package/dist-lib/storage/index.d.ts +1 -1
- package/dist-lib/storage/persistentStorage.d.ts +10 -0
- package/dist-lib/storage/schema.d.ts +166 -4
- package/dist-lib/styles.css +1 -1
- package/dist-lib/ui/BundledGameGrid.d.ts +21 -0
- package/dist-lib/ui/CharLoginModal.d.ts +5 -1
- package/dist-lib/ui/CommandBar.d.ts +7 -1
- package/dist-lib/ui/ConnectionGrid.d.ts +4 -1
- package/dist-lib/ui/FileBrowserModal.d.ts +1 -0
- package/dist-lib/ui/FilePickerModal.d.ts +3 -3
- package/dist-lib/ui/HelpModal.d.ts +11 -0
- package/dist-lib/ui/LogBrowserModal.d.ts +4 -1
- package/dist-lib/ui/PlayerMarkerPreview.d.ts +20 -0
- package/dist-lib/ui/SettingsModal.d.ts +5 -1
- package/dist-lib/ui/TlsAlertBanner.d.ts +18 -0
- package/dist-lib/ui/TlsCertificateBox.d.ts +20 -0
- package/dist-lib/ui/TlsUpgradeModal.d.ts +16 -0
- package/dist-lib/ui/Toolbar.d.ts +2 -1
- package/dist-lib/ui/VfsPickerModal.d.ts +26 -0
- package/dist-lib/ui/components/FileSourceButton.d.ts +47 -0
- package/dist-lib/ui/components/index.d.ts +1 -0
- package/dist-lib/ui/components/useModalFocus.d.ts +6 -0
- package/dist-lib/ui/helpTopics.d.ts +19 -0
- package/dist-lib/ui/labels/LabelManager.d.ts +32 -0
- package/dist-lib/ui/labels/labelLinks.d.ts +52 -0
- package/dist-lib/ui/layout/ScriptWindow.d.ts +11 -2
- package/dist-lib/ui/markdown.d.ts +10 -1
- package/dist-lib/ui/output/OutputArea.d.ts +11 -1
- package/dist-lib/ui/output/OutputContextMenu.d.ts +3 -1
- package/dist-lib/ui/output/OutputRenderer.d.ts +7 -1
- package/dist-lib/ui/output/OutputSearchBar.d.ts +25 -0
- package/dist-lib/ui/output/StickyOutputPanel.d.ts +5 -1
- package/dist-lib/ui/output/linkNavigation.d.ts +22 -0
- package/dist-lib/ui/output/outputSearch.d.ts +130 -0
- package/dist-lib/ui/search/matcher.d.ts +15 -0
- package/dist-lib/ui/search/useDebounced.d.ts +3 -0
- package/dist-lib/ui/tts/TtsManager.d.ts +3 -0
- package/dist-lib/ui/useCommandHistory.d.ts +4 -2
- package/dist-lib/ui/useOpenProfiles.d.ts +26 -0
- package/dist-lib/ui/video/VideoManager.d.ts +17 -0
- package/dist-lib/ui/windows/WindowManager.d.ts +149 -2
- package/dist-lib/ui/windows/panels/MapPanel.d.ts +4 -1
- package/dist-lib/ui/windows/panels/PackageExportModal.d.ts +18 -0
- package/dist-lib/ui/windows/panels/TextPanel.d.ts +3 -1
- package/dist-lib/ui/windows/types.d.ts +35 -0
- package/dist-lib/utils/describeThrown.d.ts +22 -0
- package/dist-lib/utils/fontLoader.d.ts +5 -0
- package/dist-lib/vfs-sw.js +131 -131
- package/dist-lib/vite.js +22 -0
- package/package.json +97 -93
- package/dist-lib/scripting/lua/mudlet-lua/generic-mapper/generic_mapper.mpackage +0 -0
- package/dist-lib/ui/windows/panels/VfsModulePickerModal.d.ts +0 -8
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Undoing the game's own line wrapping — Mudlet's `undoServerWrap` /
|
|
3
|
+
* `undoServerWrapWidth` (`TBuffer.cpp`).
|
|
4
|
+
*
|
|
5
|
+
* Many MUDs word-wrap their output server-side at a fixed column. That makes
|
|
6
|
+
* triggers awkward to write (a phrase can be split across two "lines" that were
|
|
7
|
+
* never separate) and pins the display to the game's width instead of the
|
|
8
|
+
* window's. Turning the option on holds back any line that ends where the game's
|
|
9
|
+
* wrapper would have broken it and glues the continuation on, so triggers and
|
|
10
|
+
* rendering see one whole logical line.
|
|
11
|
+
*
|
|
12
|
+
* The heuristics live here as pure functions over *visible* text so they can be
|
|
13
|
+
* tested directly, and so the pipeline glue in `ScriptingEngine` stays readable.
|
|
14
|
+
*
|
|
15
|
+
* **Visible text, not raw.** Mudlet judges `mMudLine`, which is plain characters
|
|
16
|
+
* with the styling held alongside in a `TChar` buffer. mudix keeps styling
|
|
17
|
+
* inline as ANSI escapes, so every predicate here takes text that has been put
|
|
18
|
+
* through {@link visibleText} first — otherwise a colour-heavy line would be
|
|
19
|
+
* measured as far longer than the player sees, and its escape punctuation would
|
|
20
|
+
* drag the letter ratio below the prose threshold.
|
|
21
|
+
*/
|
|
22
|
+
/** How far below the configured column a line may end and still count as
|
|
23
|
+
* ending *at* it. The game breaks at the last space that fits, so a wrapped
|
|
24
|
+
* segment falls up to a word short. Mudlet's `csmServerWrapSlack`. */
|
|
25
|
+
export declare const SERVER_WRAP_SLACK = 15;
|
|
26
|
+
/** Refuse to keep joining past this visible length — a runaway join would
|
|
27
|
+
* otherwise swallow a whole screen. Mudlet's `csmServerWrapMaxJoinedLength`. */
|
|
28
|
+
export declare const SERVER_WRAP_MAX_JOINED_LENGTH = 10000;
|
|
29
|
+
/** How much clear room the continuation's first word must have had on the line
|
|
30
|
+
* above before that line counts as one the game ended itself. Mudlet's
|
|
31
|
+
* `csmServerWrapFitTolerance` — only *clear* room disproves a wrap, because a
|
|
32
|
+
* segment inside the join band already sits up to {@link SERVER_WRAP_SLACK}
|
|
33
|
+
* short of the column. */
|
|
34
|
+
export declare const SERVER_WRAP_FIT_TOLERANCE = 8;
|
|
35
|
+
/** Longest run of digits a bare list label may carry (`1.`, `12)`, `999.`).
|
|
36
|
+
* Mudlet's `csmMaxListNumberDigits`. Bracketed labels are exempt — `[1366]` is
|
|
37
|
+
* a label however long it runs, where a bare `1364.` is as likely a price. */
|
|
38
|
+
export declare const MAX_LIST_NUMBER_DIGITS = 3;
|
|
39
|
+
/** How much of a held game line's opening is kept for comparing a continuation
|
|
40
|
+
* against. Mudlet's `csmServerWrapSegmentStartChars` — only the first
|
|
41
|
+
* {@link SERVER_WRAP_REPEATED_WORDS} shared words and the spaces after them
|
|
42
|
+
* have to fall inside it, and that leaves room for it even where a long name
|
|
43
|
+
* is one of them. */
|
|
44
|
+
export declare const SERVER_WRAP_SEGMENT_START_CHARS = 48;
|
|
45
|
+
/** How many opening words a continuation has to share with the held segment
|
|
46
|
+
* before it is a message the game re-prefixed rather than a wrap. Mudlet's
|
|
47
|
+
* `csmServerWrapRepeatedWords` — one is far too common in prose to prove
|
|
48
|
+
* anything. */
|
|
49
|
+
export declare const SERVER_WRAP_REPEATED_WORDS = 2;
|
|
50
|
+
/** How long a held-back line waits for its continuation before being committed
|
|
51
|
+
* on its own. Mudlet's `csmServerWrapFlushDelayMs`. */
|
|
52
|
+
export declare const SERVER_WRAP_FLUSH_DELAY_MS = 300;
|
|
53
|
+
/** Bounds on `undoServerWrapWidth`, matching Mudlet's `setConfig` validation
|
|
54
|
+
* (and the `qBound` its profile-XML import applies). */
|
|
55
|
+
export declare const SERVER_WRAP_WIDTH_MIN = 20;
|
|
56
|
+
export declare const SERVER_WRAP_WIDTH_MAX = 500;
|
|
57
|
+
/** Mudlet's `Host::mUndoServerWrapWidth` default. */
|
|
58
|
+
export declare const SERVER_WRAP_WIDTH_DEFAULT = 80;
|
|
59
|
+
/** Strip ANSI/OSC escapes so a line can be measured and classified the way the
|
|
60
|
+
* player sees it. Uses the shared scanner, so it skips CSI, OSC, DCS-family and
|
|
61
|
+
* short escapes alike rather than guessing at a regex. */
|
|
62
|
+
export declare function visibleText(line: string): string;
|
|
63
|
+
/**
|
|
64
|
+
* Mudlet `TBuffer::endsAtServerWrapColumn`. True when a segment's visible length
|
|
65
|
+
* lands in the `[width - slack, width]` band — i.e. where the game's own word
|
|
66
|
+
* wrap would have broken it.
|
|
67
|
+
*/
|
|
68
|
+
export declare function endsAtServerWrapColumn(visibleLength: number, width: number): boolean;
|
|
69
|
+
/**
|
|
70
|
+
* Mudlet `TBuffer::looksLikeWrappedProse`. Word-wrapped prose breaks *between
|
|
71
|
+
* words*, so a wrapped segment ends in a word (or a sentence mark that happened
|
|
72
|
+
* to land on the wrap column) and is mostly letters. ASCII art, dividers and
|
|
73
|
+
* table borders also run right up to the screen width but end in — and are full
|
|
74
|
+
* of — symbols; gluing those back together would mangle them.
|
|
75
|
+
*
|
|
76
|
+
* `visible` must already be ANSI-stripped.
|
|
77
|
+
*/
|
|
78
|
+
export declare function looksLikeWrappedProse(visible: string): boolean;
|
|
79
|
+
/**
|
|
80
|
+
* Mudlet `TBuffer::segmentEndsSettledSentence`. Where a game swallows the space
|
|
81
|
+
* it breaks at, a segment that finishes a sentence right on the wrap column
|
|
82
|
+
* looks exactly like one the game ended there itself — and games end lines on
|
|
83
|
+
* sentences all the time: a room description, the exits line below it, the
|
|
84
|
+
* object line below that. Joining those runs separate lines into one and breaks
|
|
85
|
+
* triggers anchored to their starts.
|
|
86
|
+
*
|
|
87
|
+
* A kept break space is the one piece of evidence that settles it, so only a
|
|
88
|
+
* sentence with nothing at all after it is refused — the check reads the very
|
|
89
|
+
* last character rather than the last non-space one. What that costs is a
|
|
90
|
+
* genuine wrap landing exactly after a sentence staying split, which reads as a
|
|
91
|
+
* break at a sentence boundary; far cheaper than the joins it prevents.
|
|
92
|
+
*
|
|
93
|
+
* This belongs at the *hold* decision only: continuations legitimately end
|
|
94
|
+
* sentences, so {@link looksLikeWrappedProse} must keep accepting them.
|
|
95
|
+
*
|
|
96
|
+
* `visible` must already be ANSI-stripped.
|
|
97
|
+
*/
|
|
98
|
+
export declare function segmentEndsSettledSentence(visible: string): boolean;
|
|
99
|
+
/**
|
|
100
|
+
* Mudlet `TBuffer::continuationRepeatsSegmentOpening`. Games that wrap a tell,
|
|
101
|
+
* say or channel message themselves put the whole prefix back on every physical
|
|
102
|
+
* line of it (`Anne teilt Dir mit: …`). Those lines break mid-sentence at the
|
|
103
|
+
* wrap column and leave no room for the next word, so every other check reads
|
|
104
|
+
* them as one wrapped paragraph and the join buries the prefix in the middle of
|
|
105
|
+
* it. The repeated opening is what gives them away — two words of it, because
|
|
106
|
+
* prose starts line after line with the same article or pronoun and one proves
|
|
107
|
+
* nothing.
|
|
108
|
+
*
|
|
109
|
+
* `segmentStart` is the held *game line's* opening (see
|
|
110
|
+
* {@link SERVER_WRAP_SEGMENT_START_CHARS}), not the joined paragraph's: a
|
|
111
|
+
* continuation is compared against the line it actually follows.
|
|
112
|
+
*
|
|
113
|
+
* Both strings must already be ANSI-stripped.
|
|
114
|
+
*/
|
|
115
|
+
export declare function continuationRepeatsSegmentOpening(segmentStart: string, visibleNext: string): boolean;
|
|
116
|
+
/**
|
|
117
|
+
* Mudlet `TBuffer::startsWithListMarker`. A list entry reads exactly like
|
|
118
|
+
* wrapped prose — a sentence that can end right at the wrap column — so only its
|
|
119
|
+
* marker tells a list apart from a paragraph.
|
|
120
|
+
*
|
|
121
|
+
* Every form accepted here has to be one the game's own word wrap could not
|
|
122
|
+
* produce at the start of a continuation. The ambiguous ones are deliberately
|
|
123
|
+
* left out: a spaced dash opens a continuation whenever the wrap lands on it,
|
|
124
|
+
* and a parenthesised number is as often an aside as a label, so it is capped at
|
|
125
|
+
* {@link MAX_LIST_NUMBER_DIGITS} like a bare one. Only `[...]` is exempt from
|
|
126
|
+
* the cap — nothing writes `[2500]` mid-sentence.
|
|
127
|
+
*
|
|
128
|
+
* `visible` must already be ANSI-stripped.
|
|
129
|
+
*/
|
|
130
|
+
export declare function startsWithListMarker(visible: string): boolean;
|
|
131
|
+
/**
|
|
132
|
+
* Mudlet `TBuffer::pendingLineHadRoomForNextWord`. Word wrap breaks a line for
|
|
133
|
+
* one reason only: the next word did not fit. So a continuation whose first word
|
|
134
|
+
* would have gone on the game line above it is not a continuation at all — the
|
|
135
|
+
* game ended that line itself. Without this, two sentences that each stop short
|
|
136
|
+
* of the wrap column read exactly like one wrapped paragraph.
|
|
137
|
+
*
|
|
138
|
+
* `heldSegmentLength` is the length of the last *game line* joined into the held
|
|
139
|
+
* text, not of the held text itself: once a paragraph has been joined the held
|
|
140
|
+
* text is longer than the wrap column, and the line the next word would have
|
|
141
|
+
* landed on is the one the game last sent.
|
|
142
|
+
*
|
|
143
|
+
* Both strings must already be ANSI-stripped.
|
|
144
|
+
*/
|
|
145
|
+
export declare function pendingLineHadRoomForNextWord(visiblePending: string, heldSegmentLength: number, visibleNext: string, width: number): boolean;
|
|
146
|
+
/**
|
|
147
|
+
* Mudlet's guard before joining: a genuine continuation of wrapped prose starts
|
|
148
|
+
* with a word — or with the single space some games move the break to instead of
|
|
149
|
+
* swallowing it. *Deeper* indentation, a segment that isn't prose at all, a list
|
|
150
|
+
* entry, or a first word that would have fitted on the line above all mean the
|
|
151
|
+
* held line was complete after all and must be committed on its own first.
|
|
152
|
+
*
|
|
153
|
+
* `visibleNext` must already be ANSI-stripped.
|
|
154
|
+
*/
|
|
155
|
+
export declare function shouldCommitPendingBeforeJoin(visibleNext: string, nextIsProse: boolean, fit?: {
|
|
156
|
+
visiblePending: string;
|
|
157
|
+
heldSegmentLength: number;
|
|
158
|
+
segmentStart: string;
|
|
159
|
+
width: number;
|
|
160
|
+
}): boolean;
|
|
161
|
+
/**
|
|
162
|
+
* Mudlet `TBuffer::joinPendingServerWrapOntoCurrent`. Concatenates the held line
|
|
163
|
+
* and its continuation, restoring the space the game's wrapper swallowed when
|
|
164
|
+
* neither side already carries one.
|
|
165
|
+
*
|
|
166
|
+
* Operates on the **raw** lines (escapes and all): mudix's styling is inline, so
|
|
167
|
+
* a plain concatenation carries each half's colour across untouched — the
|
|
168
|
+
* `TChar`-buffer splice Mudlet needs has no equivalent here. The space-insertion
|
|
169
|
+
* test looks at the visible text so a trailing colour reset can't hide the space
|
|
170
|
+
* that is already there.
|
|
171
|
+
*/
|
|
172
|
+
export declare function joinWrappedLines(pending: string, next: string): string;
|
|
173
|
+
/** Lines shorter than this carry no signal about a wrap column. */
|
|
174
|
+
export declare const WRAP_DETECT_MIN_LENGTH = 40;
|
|
175
|
+
/** Evaluate the collected sample only once every this many recorded lines. */
|
|
176
|
+
export declare const WRAP_DETECT_SAMPLE_INTERVAL = 100;
|
|
177
|
+
/** How many lines must sit at the ceiling before it's believable. */
|
|
178
|
+
export declare const WRAP_DETECT_THRESHOLD = 40;
|
|
179
|
+
/** A plausible wrap column has to fall in this range. */
|
|
180
|
+
export declare const WRAP_DETECT_CEILING_MIN = 60;
|
|
181
|
+
export declare const WRAP_DETECT_CEILING_MAX = 160;
|
|
182
|
+
/**
|
|
183
|
+
* Given the tally of observed line lengths, report the game's apparent wrap
|
|
184
|
+
* column, or null when the evidence doesn't support one.
|
|
185
|
+
*
|
|
186
|
+
* The ceiling is the longest length seen more than incidentally (≥3 times); it
|
|
187
|
+
* has to be a plausible screen width, carry enough lines just below it, and have
|
|
188
|
+
* almost nothing beyond it — a game that regularly emits longer lines is not
|
|
189
|
+
* wrapping at that column.
|
|
190
|
+
*/
|
|
191
|
+
export declare function detectWrapCeiling(counts: ReadonlyMap<number, number>): number | null;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ItemIdSequence } from '../ItemIdSequence';
|
|
1
2
|
import type { TimerNode } from '../../storage/schema';
|
|
2
3
|
export type { TimerNode };
|
|
3
4
|
type TempFn = () => void;
|
|
@@ -8,15 +9,23 @@ export declare class TimerEngine {
|
|
|
8
9
|
* share a name; we keep id as the canonical handle and build a separate
|
|
9
10
|
* name → id index for Mudlet's name-based lookups. */
|
|
10
11
|
private readonly perm;
|
|
11
|
-
/** Name → first matching id, used by remainingTime / kill-by-name.
|
|
12
|
+
/** Name → first matching id, used by remainingTime / kill-by-name. Only
|
|
13
|
+
* holds *armed* timers, since that is what loadPerm builds handles for. */
|
|
12
14
|
private readonly permNameToId;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
/** Every stored permanent timer name, armed or not. remainingTime needs it
|
|
16
|
+
* to tell "exists but inactive" (-1) from "no such timer" (-2): a disabled
|
|
17
|
+
* timer has no handle, so its absence from `perm` proves nothing. */
|
|
18
|
+
private readonly knownPermNames;
|
|
19
|
+
/** Shared with every other engine in the profile — see ItemIdSequence. */
|
|
20
|
+
private idSeq;
|
|
21
|
+
setIdSequence(seq: ItemIdSequence): void;
|
|
22
|
+
/** Number of live session-scoped temp timers (Mudlet `getProfileStats` temp
|
|
23
|
+
* count). Killed-but-unreaped timers are not live and don't count. */
|
|
15
24
|
get tempCount(): number;
|
|
16
25
|
addTemp(seconds: number, fn: TempFn, repeat?: boolean): number;
|
|
17
26
|
/**
|
|
18
|
-
* Fire every
|
|
19
|
-
*
|
|
27
|
+
* Fire every timer that has come due, without waiting for the event loop to
|
|
28
|
+
* deliver its setTimeout.
|
|
20
29
|
*
|
|
21
30
|
* This exists for `waitForEvent`, the busted-only helper Mudlet implements
|
|
22
31
|
* by spinning a nested QEventLoop. A browser can't re-enter its event loop,
|
|
@@ -24,15 +33,33 @@ export declare class TimerEngine {
|
|
|
24
33
|
* deadlock; pumping the due timers by hand is the equivalent of Qt draining
|
|
25
34
|
* its timer queue inside that nested loop.
|
|
26
35
|
*
|
|
27
|
-
* Repeating timers are
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
36
|
+
* Repeating timers are pumped too — Mudlet's own specs wait on a repeat
|
|
37
|
+
* tick, so skipping them made every such wait time out. That works because
|
|
38
|
+
* a repeat is a self-rescheduling setTimeout (see addTemp): the pending
|
|
39
|
+
* tick is cancelled and re-armed rather than left to land a second time.
|
|
31
40
|
*
|
|
32
41
|
* Returns the number of timers fired.
|
|
33
42
|
*/
|
|
34
43
|
pumpDue(now?: number): number;
|
|
44
|
+
/**
|
|
45
|
+
* Whether a temporary timer with this id is still present.
|
|
46
|
+
*
|
|
47
|
+
* Backs `exists(id, "timer")`. Temp timers aren't in the store and — unlike
|
|
48
|
+
* temp triggers and aliases — aren't tracked in LuaRuntime's tempIds either,
|
|
49
|
+
* so this map is the only thing that knows.
|
|
50
|
+
*
|
|
51
|
+
* There is no enable/disable for a temporary timer, so this used to answer
|
|
52
|
+
* `isActive` too. A killed one splits the two apart: it is still present
|
|
53
|
+
* here until the reap, but no longer running — see {@link tempIsActive}.
|
|
54
|
+
*/
|
|
55
|
+
hasTemp(id: number): boolean;
|
|
56
|
+
/** Whether a temporary timer is present *and* still running — `isActive(id,
|
|
57
|
+
* "timer")`. False for one killed since the last reap. */
|
|
58
|
+
tempIsActive(id: number): boolean;
|
|
35
59
|
killTimer(id: number): boolean;
|
|
60
|
+
/** Free every timer killed since the last call. Runs once per processed line
|
|
61
|
+
* batch, mirroring the deferred cleanup Mudlet's TTimerUnit does. */
|
|
62
|
+
reapKilled(): void;
|
|
36
63
|
/**
|
|
37
64
|
* Cached previous load. `nodes` is the TimerNode keyed by id, `desc` is the
|
|
38
65
|
* shape that determines whether the running setTimeout/setInterval is still
|
|
@@ -50,10 +77,14 @@ export declare class TimerEngine {
|
|
|
50
77
|
* Mudlet `remainingTime(idOrName)` — seconds until the next fire. For
|
|
51
78
|
* non-repeating timers, returns the time left before the one and only
|
|
52
79
|
* fire. For repeating timers, returns the time until the next tick.
|
|
53
|
-
*
|
|
80
|
+
* Mirrors Mudlet's two miss sentinels, which the Lua wrapper turns into
|
|
81
|
+
* different messages: **-1** the timer exists but isn't running (a perm
|
|
82
|
+
* timer starts inactive), **-2** nothing of that id or name exists at all.
|
|
54
83
|
* - Numeric arg: looks up tempTimer ids only.
|
|
55
|
-
* - String arg:
|
|
56
|
-
*
|
|
84
|
+
* - String arg: permanent timer names (or a raw uuid), then temp ids —
|
|
85
|
+
* a temporary timer's "name" is the number tempTimer handed back, so
|
|
86
|
+
* remainingTime(tostring(id)) has to resolve the same timer as
|
|
87
|
+
* remainingTime(id).
|
|
57
88
|
*/
|
|
58
89
|
remainingTime(idOrName: number | string): number;
|
|
59
90
|
private stopPerm;
|
|
@@ -35,9 +35,24 @@ export type TriggerMatch = {
|
|
|
35
35
|
namedSpans?: Record<string, CaptureSpan>;
|
|
36
36
|
matchStart?: number;
|
|
37
37
|
};
|
|
38
|
+
/** The lineage a trigger created mid-pass belongs to, and how many generations
|
|
39
|
+
* deep it sits in it. Absent on a trigger that was not created while a line was
|
|
40
|
+
* being processed. See TriggerEngine.addedWhileProcessing. */
|
|
41
|
+
interface SameLineChain {
|
|
42
|
+
chainId: number;
|
|
43
|
+
generation: number;
|
|
44
|
+
}
|
|
45
|
+
/** What a caller can tell the engine about a temp trigger beyond its pattern. */
|
|
46
|
+
export interface TempOptions {
|
|
47
|
+
/** As the runaway report names it. Mudlet uses the trigger's id when the
|
|
48
|
+
* call carried no name of its own. */
|
|
49
|
+
name?: string;
|
|
50
|
+
onStopped?: () => void;
|
|
51
|
+
}
|
|
38
52
|
export declare class TriggerEngine {
|
|
39
53
|
private readonly temp;
|
|
40
|
-
|
|
54
|
+
/** Key for this engine's own temp map — see PatternEngine.nextInternalId. */
|
|
55
|
+
private nextInternalId;
|
|
41
56
|
private inProcessTemp;
|
|
42
57
|
private permCompiled;
|
|
43
58
|
private allById;
|
|
@@ -45,12 +60,32 @@ export declare class TriggerEngine {
|
|
|
45
60
|
private permReg;
|
|
46
61
|
private unified;
|
|
47
62
|
private orderDirty;
|
|
63
|
+
private processingDepth;
|
|
64
|
+
private addedWhileProcessing;
|
|
65
|
+
/** Lineage of each permanent ROOT trigger enrolled for the current line. */
|
|
66
|
+
private permSameLine;
|
|
67
|
+
/** Lineage id → name of the trigger whose script started it, for the report. */
|
|
68
|
+
private sameLineChainStarters;
|
|
69
|
+
private lastSameLineChainId;
|
|
70
|
+
private currentSameLineChainId;
|
|
71
|
+
private currentSameLineGeneration;
|
|
72
|
+
/** The name of the trigger whose script is running, for the abort report. */
|
|
73
|
+
private currentExecutingTriggerName;
|
|
74
|
+
/** When the runaway report was last posted, so a runaway whose creator
|
|
75
|
+
* outlives its line cannot bury the game text. */
|
|
76
|
+
private lastRunawayReportAt;
|
|
48
77
|
private cache;
|
|
49
78
|
private lineCounter;
|
|
50
79
|
private readonly chainOpenUntil;
|
|
51
80
|
private hasChildren;
|
|
52
81
|
private andStates;
|
|
82
|
+
/** Triggers still firing on their own after completing, and the match they
|
|
83
|
+
* re-report while they do. See the fire-length branch in matchPermEntryOnce. */
|
|
84
|
+
private keepFiring;
|
|
53
85
|
private filterActiveText;
|
|
86
|
+
/** Every offering a filter makes to its children this line: one per
|
|
87
|
+
* capture group, or the whole match when it has none. See openChain. */
|
|
88
|
+
private filterCaptures;
|
|
54
89
|
private filterActiveOffset;
|
|
55
90
|
/** Resolves once PCRE wasm is initialized and patterns can be compiled. */
|
|
56
91
|
static ready(): Promise<void>;
|
|
@@ -78,7 +113,7 @@ export declare class TriggerEngine {
|
|
|
78
113
|
* Invalid regex patterns return a no-op disposer so callers don't need
|
|
79
114
|
* to special-case compile failures.
|
|
80
115
|
*/
|
|
81
|
-
addTemp(pattern: string, fn: TempFn, kind?: 'regex' | 'substring' | 'startOfLine' | 'exactMatch' | 'prompt'): () => void;
|
|
116
|
+
addTemp(pattern: string, fn: TempFn, kind?: 'regex' | 'substring' | 'startOfLine' | 'exactMatch' | 'prompt', opts?: TempOptions): () => void;
|
|
82
117
|
/**
|
|
83
118
|
* Mudlet `tempLineTrigger(from, howMany, fn)`. A position-based trigger with
|
|
84
119
|
* no pattern: it fires `fn([lineText])` on `howMany` consecutive lines,
|
|
@@ -95,9 +130,15 @@ export declare class TriggerEngine {
|
|
|
95
130
|
* negative result is cached so we don't retry on every loadPerm. */
|
|
96
131
|
private compileItem;
|
|
97
132
|
processTemp(line: string, isPrompt?: boolean): void;
|
|
133
|
+
/** Leave a processing pass, and once the outermost one is over, forget the
|
|
134
|
+
* lineages it tracked: a trigger that outlives the line it was created on
|
|
135
|
+
* is no longer part of one, so what IT creates later starts counting
|
|
136
|
+
* afresh. */
|
|
137
|
+
private endPass;
|
|
98
138
|
/** Match + fire a single temp trigger against `line`. Self-expiring `line`
|
|
99
139
|
* triggers delete themselves (and dirty the unified order) when spent. */
|
|
100
140
|
private fireTempEntry;
|
|
141
|
+
private fireTempEntryInner;
|
|
101
142
|
matchPerm(line: string, isPrompt?: boolean): TriggerMatch[];
|
|
102
143
|
/**
|
|
103
144
|
* Match one permanent compiled entry against `line`, appending any matches
|
|
@@ -106,6 +147,9 @@ export declare class TriggerEngine {
|
|
|
106
147
|
* shared across all entries processed for that line.
|
|
107
148
|
*/
|
|
108
149
|
private matchPermEntry;
|
|
150
|
+
/** The nearest filter ancestor of `item`, or null when it has none. */
|
|
151
|
+
private innermostFilterId;
|
|
152
|
+
private matchPermEntryOnce;
|
|
109
153
|
/**
|
|
110
154
|
* Mudlet-faithful single pass: walk the one ordered list of permanent and
|
|
111
155
|
* temporary triggers (see the ordering notes on the fields) and, for each
|
|
@@ -122,6 +166,53 @@ export declare class TriggerEngine {
|
|
|
122
166
|
* re-entrancy a handler can cause via `feedTriggers`.
|
|
123
167
|
*/
|
|
124
168
|
process(line: string, isPrompt: boolean, exec: (match: TriggerMatch) => void): void;
|
|
169
|
+
/**
|
|
170
|
+
* Enrol a trigger armed while a line was being processed, so the pass can
|
|
171
|
+
* offer it that line, and put it in a lineage: the one belonging to the
|
|
172
|
+
* trigger whose script armed it, a generation on, or a new one when the
|
|
173
|
+
* script predates the line.
|
|
174
|
+
*/
|
|
175
|
+
private registerSameLineCreation;
|
|
176
|
+
/**
|
|
177
|
+
* The same, for a permanent trigger a script created mid-pass. Only ROOT
|
|
178
|
+
* triggers carry a lineage: one sitting in a folder creates on the folder's
|
|
179
|
+
* behalf, and reading the child's own (always empty) lineage instead would
|
|
180
|
+
* start a fresh one every round — which never deepens and so never trips.
|
|
181
|
+
*/
|
|
182
|
+
notePermCreated(node: TriggerNode, root: TriggerNode): void;
|
|
183
|
+
/** Join the lineage of the trigger whose script is running, a generation on;
|
|
184
|
+
* or start one when that script predates the line. */
|
|
185
|
+
private nextSameLineChain;
|
|
186
|
+
/** The lineage of something enrolled for this line, whichever kind it is. */
|
|
187
|
+
private sameLineOf;
|
|
188
|
+
/** The root ancestor's id — the node a lineage is recorded against. */
|
|
189
|
+
private rootIdOf;
|
|
190
|
+
/** Run a permanent trigger's script inside its lineage, so what it creates
|
|
191
|
+
* is enrolled behind it rather than starting a lineage of its own. */
|
|
192
|
+
private execPerm;
|
|
193
|
+
/**
|
|
194
|
+
* Run `fn` as the script of the trigger named `name`, so anything it arms
|
|
195
|
+
* joins that trigger's lineage rather than starting one of its own.
|
|
196
|
+
*/
|
|
197
|
+
runAsTrigger<T>(name: string, sameLine: SameLineChain | undefined, fn: () => T): T;
|
|
198
|
+
/**
|
|
199
|
+
* End a lineage that keeps arming triggers which match the line being
|
|
200
|
+
* processed. Stopping the pass alone would not do: what it created is still
|
|
201
|
+
* live, so the next line would start with a budget's worth of them and each
|
|
202
|
+
* would spawn a budget's worth again. Only this lineage is disowned — a
|
|
203
|
+
* capture trigger an unrelated script armed on the same line belongs to a
|
|
204
|
+
* lineage of its own and is left alone.
|
|
205
|
+
*/
|
|
206
|
+
private stopSameLineCreationLoop;
|
|
207
|
+
/** Tell the player, at most once every REPORT interval — a runaway whose
|
|
208
|
+
* creator outlives the line trips on every matching line, and an unthrottled
|
|
209
|
+
* report would bury the game text it is trying to explain. */
|
|
210
|
+
private reportRunaway;
|
|
211
|
+
/** Where the runaway report is printed. ScriptingEngine wires this to the
|
|
212
|
+
* main console; unset (tests, teardown) the report is dropped. */
|
|
213
|
+
setRunawayReporter(fn: ((text: string) => void) | null): void;
|
|
214
|
+
/** How the engine switches off a permanent trigger it stopped. */
|
|
215
|
+
setPermDisabler(fn: ((nodeId: string) => void) | null): void;
|
|
125
216
|
/** Rebuild the merged, path-sorted processing list from the current
|
|
126
217
|
* permanent entries and temporary triggers. Called lazily from process()
|
|
127
218
|
* when either source changed. */
|
|
@@ -137,9 +228,27 @@ export declare class TriggerEngine {
|
|
|
137
228
|
* `ScriptingAPI.currentLineMatchesColor`. Passing `null` disables every
|
|
138
229
|
* colour trigger (e.g. during runtime teardown).
|
|
139
230
|
*/
|
|
140
|
-
setColorMatcher(fn: ((fg: number, bg: number
|
|
231
|
+
setColorMatcher(fn: ((fg: number, bg: number, window: {
|
|
232
|
+
start: number;
|
|
233
|
+
length: number;
|
|
234
|
+
} | null) => boolean) | null): void;
|
|
141
235
|
destroy(): void;
|
|
236
|
+
/**
|
|
237
|
+
* Advance every state an AND trigger has in flight against this line, and
|
|
238
|
+
* report the ones that completed on it.
|
|
239
|
+
*
|
|
240
|
+
* States are a LIST, not one: a trigger whose first condition matches twice
|
|
241
|
+
* before its second ever does has two matches part-way through, and both
|
|
242
|
+
* complete when that second condition finally arrives. Keeping a single
|
|
243
|
+
* state let the newer one overwrite the older, so only one ever fired.
|
|
244
|
+
*/
|
|
142
245
|
private processAndTrigger;
|
|
246
|
+
/** Carry one in-flight state as far through the remaining conditions as this
|
|
247
|
+
* line takes it. Several can be satisfied by the same line. */
|
|
248
|
+
private advanceAndState;
|
|
249
|
+
/** The match a completed AND state reports: every line's captures, in order,
|
|
250
|
+
* as `multimatches`. */
|
|
251
|
+
private andMatch;
|
|
143
252
|
/**
|
|
144
253
|
* Record a chain-head match: open the chain for `fireLength` more lines and,
|
|
145
254
|
* if the trigger is also a filter, stash the captured/matched text so
|
|
@@ -1,4 +1,14 @@
|
|
|
1
|
+
import type { TriggerPattern } from '../storage/schema';
|
|
1
2
|
import type { InstallOutcome } from './ScriptingAPI';
|
|
3
|
+
/**
|
|
4
|
+
* The item families the tree-walking APIs accept, lowercased — Mudlet's
|
|
5
|
+
* "'alias', 'button', 'script', 'keybind', 'timer' or 'trigger'", plus the
|
|
6
|
+
* 'key' spelling the engine already treats as 'keybind'. Lives here rather than
|
|
7
|
+
* on the engine so the no-op host below answers the same list: a runtime with no
|
|
8
|
+
* engine wired has no items, but it still knows what an item type IS, and
|
|
9
|
+
* reporting a valid type as invalid would send a caller looking for a typo.
|
|
10
|
+
*/
|
|
11
|
+
export declare const KNOWN_ITEM_TYPES: ReadonlySet<string>;
|
|
2
12
|
/**
|
|
3
13
|
* Everything {@link ScriptingAPI} needs from {@link ScriptingEngine}.
|
|
4
14
|
*
|
|
@@ -15,6 +25,22 @@ import type { InstallOutcome } from './ScriptingAPI';
|
|
|
15
25
|
*
|
|
16
26
|
* Members are grouped the way the engine groups them, not alphabetically.
|
|
17
27
|
*/
|
|
28
|
+
/** What tempComplexRegexTrigger asks for: a session-scoped trigger carrying
|
|
29
|
+
* everything a permanent one can. See ScriptingEngine.createTempComplexTrigger. */
|
|
30
|
+
export interface TempComplexTriggerSpec {
|
|
31
|
+
name: string;
|
|
32
|
+
patterns: TriggerPattern[];
|
|
33
|
+
code: string;
|
|
34
|
+
multiline: boolean;
|
|
35
|
+
isFilter: boolean;
|
|
36
|
+
multipleMatches: boolean;
|
|
37
|
+
fireLength: number;
|
|
38
|
+
delta: number;
|
|
39
|
+
highlight?: {
|
|
40
|
+
fg?: string;
|
|
41
|
+
bg?: string;
|
|
42
|
+
};
|
|
43
|
+
}
|
|
18
44
|
export interface EngineHost {
|
|
19
45
|
/** Run a chunk of Lua on behalf of a clicked hyperlink. Errors are reported
|
|
20
46
|
* through the API's error channel rather than thrown. */
|
|
@@ -34,9 +60,12 @@ export interface EngineHost {
|
|
|
34
60
|
requestReconnect(): boolean;
|
|
35
61
|
/** Run a synthetic batch of lines through the same pipeline as network
|
|
36
62
|
* output, so `feedTriggers` shares ordering semantics with real data. */
|
|
63
|
+
/** `fromServer` distinguishes a batch that came off the socket from one a
|
|
64
|
+
* script synthesised (feedTriggers). Absent means the socket. */
|
|
37
65
|
processFlushBatch(groups: {
|
|
38
66
|
text: string;
|
|
39
67
|
type: string;
|
|
68
|
+
fromServer?: boolean;
|
|
40
69
|
}[]): void;
|
|
41
70
|
/** Apply any coalesced trigger/alias reloads immediately instead of on the
|
|
42
71
|
* scheduled microtask. The Mudlet `perm…`, `enableTrigger` and
|
|
@@ -54,6 +83,8 @@ export interface EngineHost {
|
|
|
54
83
|
installModuleFromPath(path: string): InstallOutcome;
|
|
55
84
|
uninstallModuleByName(name: string): boolean;
|
|
56
85
|
syncModuleToFile(name: string): Promise<void>;
|
|
86
|
+
/** Write every module flagged to sync back out to its own file. */
|
|
87
|
+
saveSyncedModules(): void;
|
|
57
88
|
reloadModuleFromFile(name: string): boolean;
|
|
58
89
|
setModuleSync(name: string, sync: boolean): void;
|
|
59
90
|
getModuleSync(name: string): boolean;
|
|
@@ -75,12 +106,22 @@ export interface EngineHost {
|
|
|
75
106
|
/** Read raw bytes from the profile VFS, or null if missing/unreadable.
|
|
76
107
|
* Backs synchronous binary consumers such as setMovie's GIF decoder. */
|
|
77
108
|
readFileBytes(path: string): Uint8Array | null;
|
|
109
|
+
/** Write raw bytes into the VFS, creating parent directories. False with no
|
|
110
|
+
* VFS or when the write throws. Paths are absolute, so this also reaches
|
|
111
|
+
* outside the profile — the shared window layout lives beside the profiles
|
|
112
|
+
* folder, not inside one. */
|
|
113
|
+
writeFileBytes(path: string, bytes: Uint8Array): boolean;
|
|
114
|
+
/** Absolute VFS path of the directory that holds every profile folder —
|
|
115
|
+
* Mudlet's configuration directory, where files shared between profiles
|
|
116
|
+
* (the window layout) live. Null with no VFS. */
|
|
117
|
+
configDirectory(): string | null;
|
|
78
118
|
toggleScriptByName(name: string, enabled: boolean): boolean;
|
|
79
119
|
toggleTriggerByName(name: string, enabled: boolean): boolean;
|
|
80
120
|
toggleTimerByName(name: string, enabled: boolean): boolean;
|
|
81
121
|
toggleAliasByName(name: string, enabled: boolean): boolean;
|
|
82
122
|
toggleKeyByName(name: string, enabled: boolean): boolean;
|
|
83
|
-
|
|
123
|
+
/** Null when the toolbar moved, otherwise why it did not. */
|
|
124
|
+
toggleToolBarByName(name: string, show: boolean): string | null;
|
|
84
125
|
setTriggerStayOpenByName(name: string, lines: number): boolean;
|
|
85
126
|
/** The saved keybinding carrying this numeric id, or null — getKeyCode
|
|
86
127
|
* resolves a permanent key by the id permKey returned, not only by name. */
|
|
@@ -104,12 +145,19 @@ export interface EngineHost {
|
|
|
104
145
|
node: string;
|
|
105
146
|
isActive: boolean;
|
|
106
147
|
}> | null;
|
|
107
|
-
findItemsByName(name: string, type: string, exact: boolean, caseSensitive: boolean): number[];
|
|
148
|
+
findItemsByName(name: string, type: string, exact: boolean, caseSensitive: boolean): number[] | null;
|
|
149
|
+
/** Whether `type` names an item family at all. */
|
|
150
|
+
isKnownItemType(type: string): boolean;
|
|
151
|
+
/** Next id from the profile's single item-id sequence. Temporary items draw
|
|
152
|
+
* from it too, so a temp and a permanent item can never collide. */
|
|
153
|
+
allocateItemId(): number;
|
|
108
154
|
isAncestorsActiveById(id: number, type: string): boolean | null;
|
|
109
155
|
getProfileStats(): Record<string, unknown>;
|
|
110
156
|
createPermScript(name: string, parent: string, code: string): number;
|
|
111
157
|
createPermRegexTrigger(name: string, parent: string, regexes: string[], code: string): number;
|
|
112
158
|
createPermSubstringTrigger(name: string, parent: string, patterns: string[], code: string): number;
|
|
159
|
+
createTempComplexTrigger(spec: TempComplexTriggerSpec): number;
|
|
160
|
+
removeTemporaryTriggerById(id: number): boolean;
|
|
113
161
|
createPermBeginOfLineStringTrigger(name: string, parent: string, patterns: string[], code: string): number;
|
|
114
162
|
createPermExactMatchTrigger(name: string, parent: string, patterns: string[], code: string): number;
|
|
115
163
|
createPermPromptTrigger(name: string, parent: string, code: string): number;
|
|
@@ -120,14 +168,19 @@ export interface EngineHost {
|
|
|
120
168
|
createPermKey(name: string, parent: string, modifier: number, key: string | number, code: string): number;
|
|
121
169
|
createTempButton(toolbar: string, name: string, code: string, orientation: number): number;
|
|
122
170
|
createTempButtonToolbar(name: string, orientation: number, location: number): number;
|
|
171
|
+
/** True when the state actually changed; false when it already was that. */
|
|
123
172
|
setButtonStateByName(name: string, state: boolean): boolean;
|
|
124
173
|
getButtonStateByName(name: string): boolean | null;
|
|
174
|
+
/** Which of Mudlet's button refusals applies to `name`. */
|
|
175
|
+
buttonKindByName(name: string): 'missing' | 'plain' | 'pushdown';
|
|
125
176
|
setButtonStyleSheetByName(name: string, css: string): boolean;
|
|
126
177
|
setScriptByName(name: string, code: string, pos: number): number;
|
|
127
178
|
getScriptByName(name: string, pos: number): {
|
|
128
179
|
code: string;
|
|
129
|
-
|
|
180
|
+
id: number;
|
|
130
181
|
} | null;
|
|
182
|
+
/** Remove the script with this numeric id; true when one was removed. */
|
|
183
|
+
removeScriptById(id: number): boolean;
|
|
131
184
|
/** Mudlet's killTimer/killAlias/killTrigger/killKey by permanent-item name. */
|
|
132
185
|
killByName(kind: 'timer' | 'alias' | 'trigger' | 'key', name: string): boolean;
|
|
133
186
|
/** Mudlet `resetProfile()` — reload the profile with a fresh Lua VM. */
|
|
@@ -49,7 +49,15 @@ export interface IScriptingRuntime {
|
|
|
49
49
|
setMsspValue(name: string, value: string): void;
|
|
50
50
|
runWithMatches(code: string, name: string, matches: (string | undefined)[], multimatches?: (string | undefined)[][], namedGroups?: Record<string, string>, captureSpans?: CaptureSpan[], namedSpans?: Record<string, CaptureSpan>, fullMatchSpan?: CaptureSpan): void;
|
|
51
51
|
destroy(): void;
|
|
52
|
+
/** Bytes behind a path in the runtime's read-only bundled namespace, or null
|
|
53
|
+
* when it has none / the path is not one of them. Optional because it is a
|
|
54
|
+
* property of how a runtime ships its own library, not of running scripts:
|
|
55
|
+
* the Lua runtime serves `/lua/...` this way. */
|
|
56
|
+
readBuiltinBytes?(path: string): Uint8Array | null;
|
|
52
57
|
setCurrentLine(line: string, isPrompt: boolean): void;
|
|
58
|
+
/** The line {@link setCurrentLine} last recorded. The engine reads it back
|
|
59
|
+
* to restore the outer line after a nested feedTriggers. */
|
|
60
|
+
getCurrentLine(): string;
|
|
53
61
|
/**
|
|
54
62
|
* Mirror the last command-bar input into the Lua `command` global, matching
|
|
55
63
|
* Mudlet's AliasUnit::processDataStream. Read by scripts/keys such as the
|
|
@@ -66,6 +74,12 @@ export interface IScriptingRuntime {
|
|
|
66
74
|
* denyCurrentSend().
|
|
67
75
|
*/
|
|
68
76
|
dispatchSendRequest(text: string): boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Start a speedwalk between two rooms (Mudlet Host::startSpeedWalk): find
|
|
79
|
+
* the path and hand it to the mapper package's `doSpeedWalk`. Driven by the
|
|
80
|
+
* map's double-click-to-walk gesture via WindowManager.startSpeedWalk.
|
|
81
|
+
*/
|
|
82
|
+
startSpeedWalk(from: number, to: number): void;
|
|
69
83
|
/**
|
|
70
84
|
* Kill every event handler registered by `wrapScript` for the given
|
|
71
85
|
* script id. Called when a script is removed or disabled so its handlers
|
|
@@ -78,6 +92,9 @@ export interface IScriptingRuntime {
|
|
|
78
92
|
* (unlike permanent items) don't live in the persisted store.
|
|
79
93
|
*/
|
|
80
94
|
tempItemExists(id: number, type: string): boolean;
|
|
95
|
+
/** A live temp item of `type` carrying this script-supplied name (Mudlet's
|
|
96
|
+
* tempComplexRegexTrigger is the one temp API that takes one), or null. */
|
|
97
|
+
tempItemIdByName(name: string, type: string): number | null;
|
|
81
98
|
/** Publish one use of a server-defined MXP element as `mxp.<element>`. */
|
|
82
99
|
setMxpElement(name: string, attrs: Record<string, string>): void;
|
|
83
100
|
/** Whether a live temp item is enabled — backs `isActive(id, type)`. */
|
|
@@ -85,6 +102,11 @@ export interface IScriptingRuntime {
|
|
|
85
102
|
/** enable/disable a live temp item by id — backs enableTrigger/disableTrigger
|
|
86
103
|
* (and the alias pair) when handed the numeric id rather than a name. */
|
|
87
104
|
setTempItemEnabled(id: number, enabled: boolean): boolean;
|
|
105
|
+
/** Free every temp item killed since the last call, or only those of `type`.
|
|
106
|
+
* A killed item stops firing immediately but stays findable until here,
|
|
107
|
+
* which is Mudlet's deferred per-unit cleanup: aliases are reaped when
|
|
108
|
+
* nested alias processing unwinds, triggers when the line batch finishes. */
|
|
109
|
+
reapKilledTempItems(type?: 'alias' | 'trigger'): void;
|
|
88
110
|
/** Rebuild saved Lua globals (a Mudlet `<VariablePackage>` tree) into `_G`. */
|
|
89
111
|
restoreVariables(vars: MudletVariable[]): void;
|
|
90
112
|
/** Snapshot the save-listed globals out of `_G` into a variable tree. */
|