@mudlet/mudlet-web 0.3.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 -0
- package/README.md +150 -0
- package/dist-lib/App.d.ts +1 -0
- package/dist-lib/MudletWebApp.d.ts +11 -0
- package/dist-lib/ProfileSession.d.ts +15 -0
- package/dist-lib/assets/mapParser.worker-t-3rd1zR.js +9 -0
- package/dist-lib/branding.d.ts +213 -0
- package/dist-lib/core/EventBus.d.ts +29 -0
- package/dist-lib/db/sqliteClient.d.ts +25 -0
- package/dist-lib/hooks/useEngines.d.ts +12 -0
- package/dist-lib/hooks/useMudSession.d.ts +10 -0
- package/dist-lib/hooks/useOutput.d.ts +17 -0
- package/dist-lib/hooks/useViewportMode.d.ts +14 -0
- package/dist-lib/import/applyMudletProfile.d.ts +57 -0
- package/dist-lib/import/collectProfileExport.d.ts +16 -0
- package/dist-lib/import/defaultPackages.d.ts +81 -0
- package/dist-lib/import/defaults/mudlet-mapper.xml +13023 -0
- package/dist-lib/import/defaults/run-lua-code.mpackage +0 -0
- package/dist-lib/import/mudletHost.d.ts +67 -0
- package/dist-lib/import/mudletLink.d.ts +34 -0
- package/dist-lib/import/mudletProfileExport.d.ts +49 -0
- package/dist-lib/import/mudletProfileImport.d.ts +71 -0
- package/dist-lib/import/mudletVariables.d.ts +49 -0
- package/dist-lib/import/mudletWriteback.d.ts +12 -0
- package/dist-lib/import/mudletXmlExport.d.ts +16 -0
- package/dist-lib/import/mudletXmlImport.d.ts +21 -0
- package/dist-lib/import/packageInstaller.d.ts +72 -0
- package/dist-lib/import/packageRepository.d.ts +54 -0
- package/dist-lib/import/remotePackageInstall.d.ts +52 -0
- package/dist-lib/index.d.ts +30 -0
- package/dist-lib/index.js +42307 -0
- package/dist-lib/logging/SessionLogger.d.ts +41 -0
- package/dist-lib/main.d.ts +2 -0
- package/dist-lib/map/MapSelectionOverlay.d.ts +15 -0
- package/dist-lib/map/MapStore.d.ts +1067 -0
- package/dist-lib/map/MudixMapReader.d.ts +90 -0
- package/dist-lib/map/MudletHighlightOverlay.d.ts +18 -0
- package/dist-lib/map/mapImageExport.d.ts +26 -0
- package/dist-lib/map/mapParser.worker.d.ts +1 -0
- package/dist-lib/map/mapParserClient.d.ts +35 -0
- package/dist-lib/map/pathfinding.d.ts +52 -0
- package/dist-lib/map/xmlMapImport.d.ts +28 -0
- package/dist-lib/mud/MudSession.d.ts +236 -0
- package/dist-lib/mud/PatternEngine.d.ts +28 -0
- package/dist-lib/mud/aliases/AliasEngine.d.ts +15 -0
- package/dist-lib/mud/connection/LineAssembler.d.ts +84 -0
- package/dist-lib/mud/connection/MudClient.d.ts +268 -0
- package/dist-lib/mud/connection/PingTracker.d.ts +28 -0
- package/dist-lib/mud/connection/TelnetNegotiator.d.ts +188 -0
- package/dist-lib/mud/connection/telnetDebug.d.ts +54 -0
- package/dist-lib/mud/events.d.ts +160 -0
- package/dist-lib/mud/keybindings/KeyEngine.d.ts +36 -0
- package/dist-lib/mud/keybindings/browserReservedKeys.d.ts +45 -0
- package/dist-lib/mud/keybindings/qtKeys.d.ts +33 -0
- package/dist-lib/mud/protocol/charset.d.ts +105 -0
- package/dist-lib/mud/protocol/constants.d.ts +116 -0
- package/dist-lib/mud/protocol/echo.d.ts +63 -0
- package/dist-lib/mud/protocol/gmcp.d.ts +28 -0
- package/dist-lib/mud/protocol/index.d.ts +11 -0
- package/dist-lib/mud/protocol/mccp.d.ts +18 -0
- package/dist-lib/mud/protocol/mnes.d.ts +83 -0
- package/dist-lib/mud/protocol/msdp.d.ts +19 -0
- package/dist-lib/mud/protocol/msp.d.ts +47 -0
- package/dist-lib/mud/protocol/mssp.d.ts +25 -0
- package/dist-lib/mud/protocol/mxp.d.ts +188 -0
- package/dist-lib/mud/protocol/naws.d.ts +7 -0
- package/dist-lib/mud/replay/ReplayPlayer.d.ts +31 -0
- package/dist-lib/mud/replay/ReplayRecorder.d.ts +18 -0
- package/dist-lib/mud/replay/replayFormat.d.ts +49 -0
- package/dist-lib/mud/text/Console.d.ts +183 -0
- package/dist-lib/mud/text/FormatState.d.ts +256 -0
- package/dist-lib/mud/text/ansiEscapes.d.ts +88 -0
- package/dist-lib/mud/text/cellRender.d.ts +21 -0
- package/dist-lib/mud/text/colorParsers.d.ts +54 -0
- package/dist-lib/mud/text/colors.d.ts +31 -0
- package/dist-lib/mud/text/controlCharacterMode.d.ts +13 -0
- package/dist-lib/mud/text/controlChars.d.ts +31 -0
- package/dist-lib/mud/text/hyperlinkConfig.d.ts +164 -0
- package/dist-lib/mud/text/hyperlinkVisibility.d.ts +37 -0
- package/dist-lib/mud/text/oscLinkManager.d.ts +35 -0
- package/dist-lib/mud/text/wcwidth.d.ts +44 -0
- package/dist-lib/mud/text/xterm256.d.ts +2 -0
- package/dist-lib/mud/timers/TimerEngine.d.ts +61 -0
- package/dist-lib/mud/triggers/ChunkProcessor.d.ts +11 -0
- package/dist-lib/mud/triggers/TriggerEngine.d.ts +188 -0
- package/dist-lib/mud/triggers/pcre/Pcre2.d.ts +26 -0
- package/dist-lib/scripting/EngineHost.d.ts +152 -0
- package/dist-lib/scripting/GlobalEventChannel.d.ts +36 -0
- package/dist-lib/scripting/IScriptingRuntime.d.ts +95 -0
- package/dist-lib/scripting/MapOpenNotifier.d.ts +19 -0
- package/dist-lib/scripting/ScriptingAPI.d.ts +1691 -0
- package/dist-lib/scripting/ScriptingEngine.d.ts +806 -0
- package/dist-lib/scripting/StopwatchManager.d.ts +94 -0
- package/dist-lib/scripting/heldModifiers.d.ts +3 -0
- package/dist-lib/scripting/http/HttpService.d.ts +23 -0
- package/dist-lib/scripting/lua/LuaRuntime.d.ts +190 -0
- package/dist-lib/scripting/lua/bindings/automation.d.ts +10 -0
- package/dist-lib/scripting/lua/bindings/commandLine.d.ts +11 -0
- package/dist-lib/scripting/lua/bindings/context.d.ts +87 -0
- package/dist-lib/scripting/lua/bindings/cursor.d.ts +10 -0
- package/dist-lib/scripting/lua/bindings/diagnostics.d.ts +9 -0
- package/dist-lib/scripting/lua/bindings/map.d.ts +14 -0
- package/dist-lib/scripting/lua/bindings/media.d.ts +24 -0
- package/dist-lib/scripting/lua/bindings/output.d.ts +10 -0
- package/dist-lib/scripting/lua/bindings/packages.d.ts +10 -0
- package/dist-lib/scripting/lua/bindings/session.d.ts +16 -0
- package/dist-lib/scripting/lua/bindings/textEdit.d.ts +9 -0
- package/dist-lib/scripting/lua/bindings/userWindows.d.ts +11 -0
- package/dist-lib/scripting/lua/bindings/window.d.ts +10 -0
- package/dist-lib/scripting/lua/imageSize.d.ts +4 -0
- package/dist-lib/scripting/lua/luaCompletions.d.ts +9 -0
- package/dist-lib/scripting/lua/mudlet-lua/generic-mapper/generic_mapper.mpackage +0 -0
- package/dist-lib/scripting/lua/rex.d.ts +3 -0
- package/dist-lib/scripting/lua/sqlRowEncoder.d.ts +1 -0
- package/dist-lib/scripting/lua/yajl.d.ts +11 -0
- package/dist-lib/scripting/profilesPresence.d.ts +50 -0
- package/dist-lib/scripting/vfs/ProfileVFS.d.ts +62 -0
- package/dist-lib/scripting/vfs/cssRewrite.d.ts +21 -0
- package/dist-lib/scripting/vfs/folderHandleStore.d.ts +16 -0
- package/dist-lib/scripting/vfs/folderSync.d.ts +59 -0
- package/dist-lib/scripting/vfs/htmlRewrite.d.ts +26 -0
- package/dist-lib/scripting/vfs/vfsBridge.d.ts +16 -0
- package/dist-lib/services/cloudflare.d.ts +54 -0
- package/dist-lib/storage/appStore.d.ts +132 -0
- package/dist-lib/storage/crossTabSync.d.ts +3 -0
- package/dist-lib/storage/debouncedStorage.d.ts +18 -0
- package/dist-lib/storage/hooks.d.ts +17 -0
- package/dist-lib/storage/index.d.ts +4 -0
- package/dist-lib/storage/logExport.d.ts +32 -0
- package/dist-lib/storage/logStorage.d.ts +45 -0
- package/dist-lib/storage/mapStorage.d.ts +2 -0
- package/dist-lib/storage/profileVfsData.d.ts +47 -0
- package/dist-lib/storage/schema.d.ts +638 -0
- package/dist-lib/styles.css +2 -0
- package/dist-lib/ui/AboutModal.d.ts +8 -0
- package/dist-lib/ui/BrandLoginFields.d.ts +25 -0
- package/dist-lib/ui/BrandLoginScreen.d.ts +11 -0
- package/dist-lib/ui/CharLoginModal.d.ts +32 -0
- package/dist-lib/ui/CmdLineMenuRegistry.d.ts +27 -0
- package/dist-lib/ui/CodeEditorPreview.d.ts +19 -0
- package/dist-lib/ui/CommandBar.d.ts +17 -0
- package/dist-lib/ui/ConnectionFormModal.d.ts +13 -0
- package/dist-lib/ui/ConnectionGrid.d.ts +18 -0
- package/dist-lib/ui/ConnectionScreen.d.ts +14 -0
- package/dist-lib/ui/FileBrowserModal.d.ts +20 -0
- package/dist-lib/ui/FilePickerModal.d.ts +21 -0
- package/dist-lib/ui/FolderPermissionScreen.d.ts +16 -0
- package/dist-lib/ui/JsonPreview.d.ts +15 -0
- package/dist-lib/ui/LogBrowserModal.d.ts +7 -0
- package/dist-lib/ui/MapEditorModal.d.ts +9 -0
- package/dist-lib/ui/MarkdownPreview.d.ts +15 -0
- package/dist-lib/ui/MergeConflictModal.d.ts +17 -0
- package/dist-lib/ui/ModuleResolveModal.d.ts +22 -0
- package/dist-lib/ui/MouseEventRegistry.d.ts +31 -0
- package/dist-lib/ui/ProfileBusyScreen.d.ts +12 -0
- package/dist-lib/ui/ProfileExportModal.d.ts +7 -0
- package/dist-lib/ui/ProxyInfoModal.d.ts +6 -0
- package/dist-lib/ui/ProxyWhyModal.d.ts +6 -0
- package/dist-lib/ui/ProxyWizardModal.d.ts +6 -0
- package/dist-lib/ui/QuickOpenPalette.d.ts +8 -0
- package/dist-lib/ui/ResizableModal.d.ts +17 -0
- package/dist-lib/ui/ScriptingDocsModal.d.ts +12 -0
- package/dist-lib/ui/SettingsModal.d.ts +9 -0
- package/dist-lib/ui/Toolbar.d.ts +29 -0
- package/dist-lib/ui/bufferWords.d.ts +38 -0
- package/dist-lib/ui/buttons/ButtonsBar.d.ts +21 -0
- package/dist-lib/ui/cmdline/CommandLineManager.d.ts +97 -0
- package/dist-lib/ui/cmdline/CommandLineOverlay.d.ts +8 -0
- package/dist-lib/ui/codemirror/theme.d.ts +5 -0
- package/dist-lib/ui/commandHistory.d.ts +31 -0
- package/dist-lib/ui/components/Button.d.ts +9 -0
- package/dist-lib/ui/components/ConfirmDialog.d.ts +29 -0
- package/dist-lib/ui/components/ContextMenu.d.ts +9 -0
- package/dist-lib/ui/components/FontPicker.d.ts +9 -0
- package/dist-lib/ui/components/FormField.d.ts +16 -0
- package/dist-lib/ui/components/HelpTip.d.ts +7 -0
- package/dist-lib/ui/components/Input.d.ts +6 -0
- package/dist-lib/ui/components/Toggle.d.ts +10 -0
- package/dist-lib/ui/components/index.d.ts +9 -0
- package/dist-lib/ui/components/useModalFocus.d.ts +18 -0
- package/dist-lib/ui/labels/LabelManager.d.ts +220 -0
- package/dist-lib/ui/labels/LabelOverlay.d.ts +9 -0
- package/dist-lib/ui/labels/backgroundImageSize.d.ts +10 -0
- package/dist-lib/ui/labels/cursorShapes.d.ts +6 -0
- package/dist-lib/ui/labels/gifMovie.d.ts +100 -0
- package/dist-lib/ui/labels/qtCss.d.ts +57 -0
- package/dist-lib/ui/layout/ContentLayout.d.ts +19 -0
- package/dist-lib/ui/layout/DockArea.d.ts +14 -0
- package/dist-lib/ui/layout/DockedPanel.d.ts +13 -0
- package/dist-lib/ui/layout/FloatingWindowLayer.d.ts +10 -0
- package/dist-lib/ui/layout/MobileLayout.d.ts +22 -0
- package/dist-lib/ui/layout/PopoutWindow.d.ts +35 -0
- package/dist-lib/ui/layout/ScriptWindow.d.ts +29 -0
- package/dist-lib/ui/layout/SplitGroupPanel.d.ts +17 -0
- package/dist-lib/ui/layout/TabGroupPanel.d.ts +12 -0
- package/dist-lib/ui/layout/WindowContextMenu.d.ts +11 -0
- package/dist-lib/ui/layout/dockDetect.d.ts +26 -0
- package/dist-lib/ui/layout/overlayLayerOrder.d.ts +71 -0
- package/dist-lib/ui/markdown.d.ts +1 -0
- package/dist-lib/ui/output/CaretReviewPanel.d.ts +22 -0
- package/dist-lib/ui/output/OutputArea.d.ts +9 -0
- package/dist-lib/ui/output/OutputContextMenu.d.ts +23 -0
- package/dist-lib/ui/output/OutputRenderer.d.ts +64 -0
- package/dist-lib/ui/output/ScreenReaderLog.d.ts +23 -0
- package/dist-lib/ui/output/StickyOutputPanel.d.ts +28 -0
- package/dist-lib/ui/output/backgroundImageStyle.d.ts +17 -0
- package/dist-lib/ui/output/caretMode.d.ts +40 -0
- package/dist-lib/ui/output/linkNavigation.d.ts +29 -0
- package/dist-lib/ui/output/osc8Menu.d.ts +16 -0
- package/dist-lib/ui/output/outputCopy.d.ts +15 -0
- package/dist-lib/ui/preventPinchZoom.d.ts +1 -0
- package/dist-lib/ui/scrollbox/ScrollBoxManager.d.ts +62 -0
- package/dist-lib/ui/scrollbox/ScrollBoxOverlay.d.ts +25 -0
- package/dist-lib/ui/sound/SoundManager.d.ts +149 -0
- package/dist-lib/ui/sound/closedCaption.d.ts +37 -0
- package/dist-lib/ui/textedit/TextEditManager.d.ts +56 -0
- package/dist-lib/ui/tts/TtsManager.d.ts +68 -0
- package/dist-lib/ui/useBrandLogin.d.ts +19 -0
- package/dist-lib/ui/useCommandHistory.d.ts +7 -0
- package/dist-lib/ui/video/VideoManager.d.ts +56 -0
- package/dist-lib/ui/windows/ScriptEditorModal.d.ts +13 -0
- package/dist-lib/ui/windows/WindowManager.d.ts +694 -0
- package/dist-lib/ui/windows/panels/HtmlPanel.d.ts +27 -0
- package/dist-lib/ui/windows/panels/LuaEditor.d.ts +14 -0
- package/dist-lib/ui/windows/panels/MapPanel.d.ts +8 -0
- package/dist-lib/ui/windows/panels/PackageRepositoryModal.d.ts +18 -0
- package/dist-lib/ui/windows/panels/ScriptEditorPanel.d.ts +24 -0
- package/dist-lib/ui/windows/panels/ScriptSearch.d.ts +12 -0
- package/dist-lib/ui/windows/panels/TextPanel.d.ts +35 -0
- package/dist-lib/ui/windows/panels/VariablesView.d.ts +21 -0
- package/dist-lib/ui/windows/panels/VfsModulePickerModal.d.ts +8 -0
- package/dist-lib/ui/windows/panels/WindowCmdLine.d.ts +23 -0
- package/dist-lib/ui/windows/types.d.ts +145 -0
- package/dist-lib/utils/documentTitle.d.ts +33 -0
- package/dist-lib/utils/fontLoader.d.ts +52 -0
- package/dist-lib/utils/profileLock.d.ts +26 -0
- package/dist-lib/utils/sessionCredentials.d.ts +16 -0
- package/dist-lib/version.d.ts +39 -0
- package/dist-lib/vfs-sw.js +131 -0
- package/dist-lib/vite.d.ts +2 -0
- package/dist-lib/vite.js +154 -0
- package/package.json +93 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { CLIENT_NAME, CLIENT_VERSION, TERMINAL_TYPE } from "../../version";
|
|
2
|
+
/** A single MNES variable the client reports back, e.g. `{ name: "CHARSET",
|
|
3
|
+
* value: "UTF-8" }`. */
|
|
4
|
+
export interface MnesVar {
|
|
5
|
+
name: string;
|
|
6
|
+
value: string;
|
|
7
|
+
}
|
|
8
|
+
/** Result of parsing an `IAC SB NEW-ENVIRON SEND … IAC SE` request body. */
|
|
9
|
+
export interface MnesRequest {
|
|
10
|
+
/** True when the body is a well-formed SEND command (the only request kind
|
|
11
|
+
* a client answers). */
|
|
12
|
+
isSend: boolean;
|
|
13
|
+
/** Variable names the server explicitly asked for, in request order. Empty
|
|
14
|
+
* means a bare SEND — the server wants every variable we report. */
|
|
15
|
+
requested: string[];
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Parse an `IAC SB NEW-ENVIRON SEND …` request. `subneg` is the subnegotiation
|
|
19
|
+
* body with the leading option code (39) still attached (matching how the
|
|
20
|
+
* telnet option parser hands bodies to the other protocol streams). The byte
|
|
21
|
+
* after the option code is the command; for a server→client request it's SEND.
|
|
22
|
+
* After SEND comes an optional list of `VAR <name>` / `USERVAR <name>` entries,
|
|
23
|
+
* each name running until the next marker (ESC-escaped bytes pass through).
|
|
24
|
+
* A bare SEND with no entries — or only empty names — means "send everything".
|
|
25
|
+
*/
|
|
26
|
+
export declare function parseMnesRequest(subneg: string): MnesRequest;
|
|
27
|
+
/**
|
|
28
|
+
* Frame an `IAC SB NEW-ENVIRON IS <marker> <name> VALUE <value> … IAC SE` reply
|
|
29
|
+
* for the given variables. The returned string is a Latin-1 byte-string ready
|
|
30
|
+
* for sendBytes (names/values are ASCII; control bytes are escaped per RFC
|
|
31
|
+
* 1572). `marker` selects how each variable name is tagged: `NEW_ENVIRON_VAR`
|
|
32
|
+
* (the default — MNES frames every variable as a standard VAR) or
|
|
33
|
+
* `NEW_ENVIRON_USERVAR` (plain NEW-ENVIRON frames its client-defined variables
|
|
34
|
+
* as USERVAR, matching Mudlet). The two never mix within one reply because the
|
|
35
|
+
* client reports a single coherent set per negotiated mode.
|
|
36
|
+
*/
|
|
37
|
+
export declare function encodeMnesIs(vars: ReadonlyArray<MnesVar>, marker?: string): string;
|
|
38
|
+
/** Live client state the NEW-ENVIRON variable set is derived from. Everything
|
|
39
|
+
* here is something the server can't know on its own — the negotiated encoding,
|
|
40
|
+
* the transport's TLS status, the output window's wrap column. */
|
|
41
|
+
export interface NewEnvironState {
|
|
42
|
+
/** The active byte→char codec label as reported for the CHARSET variable,
|
|
43
|
+
* e.g. "UTF-8" or "LATIN-1". */
|
|
44
|
+
charset: string;
|
|
45
|
+
/** Whether the live encoding is UTF-8 (drives the UTF-8 capability flag). */
|
|
46
|
+
utf8: boolean;
|
|
47
|
+
/** Whether the link to the game server is TLS-encrypted. True for a direct
|
|
48
|
+
* `wss://` connection; false in proxy mode (plaintext upstream telnet). */
|
|
49
|
+
tls: boolean;
|
|
50
|
+
/** Output window wrap column, or 0 when the grid hasn't been measured yet. */
|
|
51
|
+
wrapColumns: number;
|
|
52
|
+
/** Whether the client is advertising screen-reader use (MTTS SCREEN READER
|
|
53
|
+
* bit, NEW-ENVIRON SCREEN_READER var) — `setConfig("advertiseScreenReader", …)`.
|
|
54
|
+
* Defaults to false (matching Mudlet's opt-in behaviour). */
|
|
55
|
+
screenReader?: boolean;
|
|
56
|
+
}
|
|
57
|
+
/** The five core variables MNES standardises (https://tintin.mudhalla.net/protocols/mnes/).
|
|
58
|
+
* Plain NEW-ENVIRON reports these too, plus the extended capability set below.
|
|
59
|
+
* Client name/version/terminal type come from the shared identity module so
|
|
60
|
+
* MNES, TTYPE, GMCP `Core.Hello` and MXP can't drift apart; re-exported here
|
|
61
|
+
* because the protocol barrel and `MudClient` already source them from MNES. */
|
|
62
|
+
export { CLIENT_NAME, CLIENT_VERSION, TERMINAL_TYPE };
|
|
63
|
+
/**
|
|
64
|
+
* Build the variable set the client reports for option 39. The five MNES core
|
|
65
|
+
* variables (CHARSET, CLIENT_NAME, CLIENT_VERSION, MTTS, TERMINAL_TYPE) are
|
|
66
|
+
* always present; when `extended` is true the broader NEW-ENVIRON capability
|
|
67
|
+
* set is appended (mirroring Mudlet's `getNewEnvironDataMap`): terminal
|
|
68
|
+
* capabilities (ANSI, 256_COLORS, TRUECOLOR, UTF-8), transport/security (TLS),
|
|
69
|
+
* and layout/accessibility hints (WORD_WRAP, SCREEN_READER). Capabilities mudix
|
|
70
|
+
* doesn't implement are reported honestly as "0" rather than omitted, so a
|
|
71
|
+
* server gets a definite answer instead of inferring absence. The caller frames
|
|
72
|
+
* the result with VAR (MNES) or USERVAR (NEW-ENVIRON) via encodeMnesIs.
|
|
73
|
+
*/
|
|
74
|
+
export declare function buildNewEnvironVars(state: NewEnvironState, extended: boolean): MnesVar[];
|
|
75
|
+
/**
|
|
76
|
+
* Pick which of the client's `available` MNES variables to report in response
|
|
77
|
+
* to a parsed request. A bare SEND (no specific names) returns everything;
|
|
78
|
+
* otherwise the requested names are returned in request order, filtered to the
|
|
79
|
+
* ones we actually know. If the server asked only for names we don't report,
|
|
80
|
+
* we fall back to sending everything rather than an empty reply — the server
|
|
81
|
+
* still learns who we are.
|
|
82
|
+
*/
|
|
83
|
+
export declare function selectMnesVars(request: MnesRequest, available: ReadonlyArray<MnesVar>): MnesVar[];
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Frame a Mudlet-style `sendMSDP(variable, ...values)` call as an MSDP
|
|
3
|
+
* subnegotiation: `IAC SB MSDP MSDP_VAR <variable> [MSDP_VAL <value>]... IAC SE`.
|
|
4
|
+
* The returned string is a Latin-1 byte-string ready for sendBytes.
|
|
5
|
+
*/
|
|
6
|
+
export declare function encodeMsdp(variable: string, values: string[]): string;
|
|
7
|
+
export interface MsdpEnvelope {
|
|
8
|
+
/** Top-level MSDP variable name (e.g. "HEALTH", "ROOM"). */
|
|
9
|
+
path: string;
|
|
10
|
+
/** Decoded value: a string, an array, or a nested string-keyed object. */
|
|
11
|
+
value: unknown;
|
|
12
|
+
}
|
|
13
|
+
export interface MsdpStreamOptions {
|
|
14
|
+
onEnvelope: (payload: MsdpEnvelope) => void;
|
|
15
|
+
}
|
|
16
|
+
/** Mirror of createGmcpStream for MSDP subnegotiations. The handler receives a
|
|
17
|
+
* subnegotiation body whose first byte is the MSDP option code (69); each
|
|
18
|
+
* top-level variable is emitted as its own envelope. */
|
|
19
|
+
export declare const createMsdpStream: ({ onEnvelope }: MsdpStreamOptions) => (data: string) => void;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export type MspKind = "sound" | "music";
|
|
2
|
+
/** Parsed `!!SOUND` / `!!MUSIC` command. Numeric fields fall back to undefined
|
|
3
|
+
* when the server omits the key — the consumer (SoundManager) substitutes its
|
|
4
|
+
* own defaults rather than having parser-level defaults bleed downstream. */
|
|
5
|
+
export interface MspCommand {
|
|
6
|
+
kind: MspKind;
|
|
7
|
+
/** Filename or the literal `Off` (case-sensitive per spec) to stop playback. */
|
|
8
|
+
file: string;
|
|
9
|
+
/** U= field — explicit URL the file can be downloaded from. */
|
|
10
|
+
url?: string;
|
|
11
|
+
/** V= field — volume 0..100 on the MSP scale. */
|
|
12
|
+
volume?: number;
|
|
13
|
+
/** L= field — loop count. -1 = forever, otherwise positive integer. */
|
|
14
|
+
loops?: number;
|
|
15
|
+
/** P= field — priority 0..100. Only meaningful for `!!SOUND`. */
|
|
16
|
+
priority?: number;
|
|
17
|
+
/** C= field — `1` = if same is already playing, keep it (no restart). */
|
|
18
|
+
continueIfPlaying?: boolean;
|
|
19
|
+
/** T= field — channel / tag string. */
|
|
20
|
+
type?: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Stateful MSP parser. Feed each post-telnet-strip chunk through `feed()` and
|
|
24
|
+
* render the returned `text` instead of the raw input. Parsed commands are
|
|
25
|
+
* delivered as `commands`. The parser holds back a partial tag (`!!SOUND(...`
|
|
26
|
+
* with no closing `)` yet) until the next chunk supplies the rest, so tags
|
|
27
|
+
* split across WebSocket frames still parse correctly.
|
|
28
|
+
*/
|
|
29
|
+
export declare class MspParser {
|
|
30
|
+
/** Partial tag carried over from the previous chunk, including the
|
|
31
|
+
* leading `!!`. Empty when no tag is in progress. */
|
|
32
|
+
private pending;
|
|
33
|
+
feed(input: string): {
|
|
34
|
+
text: string;
|
|
35
|
+
commands: MspCommand[];
|
|
36
|
+
};
|
|
37
|
+
/** Drop any partial-tag buffer. Called on disconnect / reconnect. */
|
|
38
|
+
reset(): void;
|
|
39
|
+
/** Parse the body of an `IAC SB MSP ... IAC SE` subnegotiation. The body
|
|
40
|
+
* byte[0] is the option code (90); the rest is the raw tag text (often
|
|
41
|
+
* `!!SOUND(...)`) per the spec, though some implementations send just the
|
|
42
|
+
* body inside the parens. We try both. A subnegotiation is framed as a
|
|
43
|
+
* whole unit by the time it reaches us, so we don't share parser state
|
|
44
|
+
* with the in-band stream — running `feed()` here would let a malformed
|
|
45
|
+
* subneg leak a partial-tag buffer into the next inline chunk. */
|
|
46
|
+
feedSubneg(subneg: string): MspCommand[];
|
|
47
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface MsspEnvelope {
|
|
2
|
+
/** MSSP variable name (e.g. "PLAYERS", "UPTIME", "HOSTNAME"). */
|
|
3
|
+
name: string;
|
|
4
|
+
/** The reported value. Always a string — Mudlet treats MSSP values as
|
|
5
|
+
* scalars (the multi-value list form, rare in practice, is collapsed to
|
|
6
|
+
* the first value). */
|
|
7
|
+
value: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Parse an MSSP subnegotiation body (the `IAC SB MSSP … IAC SE` payload with
|
|
11
|
+
* the leading option byte already stripped). The grammar is a flat run of
|
|
12
|
+
* `MSSP_VAR <name> MSSP_VAL <value>` pairs; names/values are scalar byte runs
|
|
13
|
+
* terminated by the next control byte. Tolerant of truncation and stray bytes.
|
|
14
|
+
*
|
|
15
|
+
* Mirrors Mudlet's TLuaInterpreter::parseMSSP: scalar string values, and a
|
|
16
|
+
* variable with extra `MSSP_VAL` runs keeps only its first value.
|
|
17
|
+
*/
|
|
18
|
+
export declare function parseMssp(body: string): MsspEnvelope[];
|
|
19
|
+
export interface MsspStreamOptions {
|
|
20
|
+
onEnvelope: (payload: MsspEnvelope) => void;
|
|
21
|
+
}
|
|
22
|
+
/** Mirror of createMsdpStream for MSSP subnegotiations. The handler receives a
|
|
23
|
+
* subnegotiation body whose first byte is the MSSP option code (70); each
|
|
24
|
+
* variable is emitted as its own envelope. */
|
|
25
|
+
export declare const createMsspStream: ({ onEnvelope }: MsspStreamOptions) => (data: string) => void;
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import type { BufferSegment, FormatStateSnapshot } from "../text/FormatState";
|
|
2
|
+
import { HyperlinkPresetRegistry } from "../text/hyperlinkConfig";
|
|
3
|
+
import type { MspCommand } from "./msp";
|
|
4
|
+
/** A clickable region the parser found, expressed as offsets into `plain`. The
|
|
5
|
+
* engine builds the actual `FormatHyperlink` (with session/URL behaviour). */
|
|
6
|
+
export interface MxpLink {
|
|
7
|
+
/** Start offset into the line's plain text (inclusive). */
|
|
8
|
+
start: number;
|
|
9
|
+
/** End offset into the line's plain text (exclusive). */
|
|
10
|
+
end: number;
|
|
11
|
+
/** `url` → open in a browser tab; `command` → send to the MUD. */
|
|
12
|
+
kind: "command" | "url";
|
|
13
|
+
/** The single command or URL fired on left-click. */
|
|
14
|
+
payload: string;
|
|
15
|
+
/** Tooltip / title text. */
|
|
16
|
+
hint?: string;
|
|
17
|
+
/** Present when the SEND carried a `cmd1|cmd2|…` list — the engine renders a
|
|
18
|
+
* right-click popup of `cmds` labelled by `hints`. */
|
|
19
|
+
prompts?: {
|
|
20
|
+
cmds: string[];
|
|
21
|
+
hints: string[];
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/** A `<FRAME>` window-lifecycle command the parser surfaces to the session.
|
|
25
|
+
* The parser is session-free, so it only reports the request; the consumer
|
|
26
|
+
* (ScriptingEngine) maps it onto a mini-console via the window manager. */
|
|
27
|
+
export interface MxpFrameCommand {
|
|
28
|
+
/** Frame name (the window id). */
|
|
29
|
+
name: string;
|
|
30
|
+
/** Upper-cased attribute keys → raw string values. Flag attributes
|
|
31
|
+
* (`INTERNAL`/`EXTERNAL`/`FLOATING`) are present with value `"true"`.
|
|
32
|
+
* `ACTION` is `open` (default) / `close` / `redirect`; geometry lives in
|
|
33
|
+
* `LEFT`/`TOP`/`WIDTH`/`HEIGHT`. */
|
|
34
|
+
attrs: Record<string, string>;
|
|
35
|
+
}
|
|
36
|
+
/** Text the parser redirected into a named frame via `<DEST>…</DEST>`. */
|
|
37
|
+
export interface MxpRedirect {
|
|
38
|
+
/** Target frame name (matches an `MxpFrameCommand.name`). */
|
|
39
|
+
frame: string;
|
|
40
|
+
/** Styled segments of the redirected text. */
|
|
41
|
+
segments: BufferSegment[];
|
|
42
|
+
/** Plain text of the redirected run. */
|
|
43
|
+
plain: string;
|
|
44
|
+
/** `EOL` attr (or the network line ended mid-DEST): the write is a complete
|
|
45
|
+
* line. */
|
|
46
|
+
eol: boolean;
|
|
47
|
+
/** `EOF` attr: clear the frame before writing (status-frame replace). */
|
|
48
|
+
eof: boolean;
|
|
49
|
+
}
|
|
50
|
+
/** The result of parsing one raw MXP line. */
|
|
51
|
+
export interface MxpLineResult {
|
|
52
|
+
/** Styled segments, ready for `new AnsiAwareBuffer(segments)`. */
|
|
53
|
+
segments: BufferSegment[];
|
|
54
|
+
/** MXP-stripped, ANSI-stripped, entity-decoded text — for trigger matching. */
|
|
55
|
+
plain: string;
|
|
56
|
+
/** End-of-line SGR/format pen, carried into the next line (replaces
|
|
57
|
+
* `computeTrailingState` while MXP is active). */
|
|
58
|
+
trailingSnapshot?: FormatStateSnapshot;
|
|
59
|
+
/** Clickable regions discovered on this line. */
|
|
60
|
+
links: MxpLink[];
|
|
61
|
+
/** `<FRAME>` commands seen on this line (window create/close). Omitted when none. */
|
|
62
|
+
frames?: MxpFrameCommand[];
|
|
63
|
+
/** Text redirected into frames via `<DEST>` on this line. Omitted when none. */
|
|
64
|
+
redirects?: MxpRedirect[];
|
|
65
|
+
/** `<SOUND>`/`<MUSIC>` audio triggers seen on this line, shaped as
|
|
66
|
+
* {@link MspCommand} so the consumer can route them through the same
|
|
67
|
+
* SoundManager path as MSP. Omitted when none. */
|
|
68
|
+
sounds?: MspCommand[];
|
|
69
|
+
}
|
|
70
|
+
export declare class MxpParser {
|
|
71
|
+
private readonly opts;
|
|
72
|
+
private elements;
|
|
73
|
+
private entities;
|
|
74
|
+
private lineMode;
|
|
75
|
+
private lockedMode;
|
|
76
|
+
private tempSecure;
|
|
77
|
+
private stack;
|
|
78
|
+
/** Active MXP `<COLOR>`/`<FONT>` fg/bg overrides, innermost last. While
|
|
79
|
+
* non-empty, the top entry's colours are painted over whatever the ANSI
|
|
80
|
+
* pen holds — matching Mudlet, where an open MXP colour element overrides
|
|
81
|
+
* embedded ANSI SGR (TBuffer.cpp: `if (hasFgColor()) c.mFgColor = ...`).
|
|
82
|
+
* Stays in sync with the colour tags on `stack` (pushed in openColor,
|
|
83
|
+
* popped in finalizeTag). */
|
|
84
|
+
private mxpColorStack;
|
|
85
|
+
/** Partial tag/entity held from the end of the previous line. */
|
|
86
|
+
private pendingTag;
|
|
87
|
+
/** Active `<DEST>` target frame (persists across lines until `</DEST>`), or
|
|
88
|
+
* null when output flows to the main window. While set, appended text and
|
|
89
|
+
* flushed runs route to `destOut`/`destPlain` instead of `out`/`plain`. */
|
|
90
|
+
private destName;
|
|
91
|
+
private destEol;
|
|
92
|
+
private destEof;
|
|
93
|
+
/** OSC 8 preset definitions seen this session (shared with the ANSI path
|
|
94
|
+
* when the engine supplies a registry). */
|
|
95
|
+
private presets;
|
|
96
|
+
private fmt;
|
|
97
|
+
private out;
|
|
98
|
+
private run;
|
|
99
|
+
private plain;
|
|
100
|
+
private links;
|
|
101
|
+
/** `<FRAME>` commands and `<DEST>` redirects accumulated this line. */
|
|
102
|
+
private frames;
|
|
103
|
+
private redirects;
|
|
104
|
+
/** `<SOUND>`/`<MUSIC>` commands accumulated this line. */
|
|
105
|
+
private sounds;
|
|
106
|
+
/** Redirected-text scratch — the current `<DEST>` run's segments/plain. */
|
|
107
|
+
private destOut;
|
|
108
|
+
private destPlain;
|
|
109
|
+
constructor(opts: {
|
|
110
|
+
send: (raw: string) => void;
|
|
111
|
+
presets?: HyperlinkPresetRegistry;
|
|
112
|
+
/** Fired whenever a server-defined custom element is used, with the
|
|
113
|
+
* tag's attributes resolved the way Mudlet resolves them (see
|
|
114
|
+
* {@link elementEventAttrs}). Backs the Lua `mxp` table. */
|
|
115
|
+
onElementEvent?: (name: string, attrs: Record<string, string>) => void;
|
|
116
|
+
});
|
|
117
|
+
/**
|
|
118
|
+
* Lock the parser to secure line mode (or release the lock). Mudlet does
|
|
119
|
+
* this whenever the MXP processor is forced on without an option-91
|
|
120
|
+
* handshake (ctelnet.cpp: MXP_MODE_CODE_LOCK_SECURE): such servers are
|
|
121
|
+
* IRE-style and never send mode switches, they just use secure tags — and
|
|
122
|
+
* without the lock every definition tag would be ignored as unsafe.
|
|
123
|
+
*/
|
|
124
|
+
lockSecureMode(locked: boolean): void;
|
|
125
|
+
/** Clear all cross-line state. Called on (re)connect so a new session starts
|
|
126
|
+
* with no leftover definitions, open tags, or modes. */
|
|
127
|
+
reset(): void;
|
|
128
|
+
/** Parse one raw line (post telnet-strip, post UTF-8 decode), which may carry
|
|
129
|
+
* ANSI SGR, MXP tags, `ESC[#z` modes, and entities. `baseSnapshot` is the
|
|
130
|
+
* carried pen from the previous line. */
|
|
131
|
+
parseLine(rawLine: string, baseSnapshot?: FormatStateSnapshot): MxpLineResult;
|
|
132
|
+
private effectiveMode;
|
|
133
|
+
private resetTransientMode;
|
|
134
|
+
private appendText;
|
|
135
|
+
private flushRun;
|
|
136
|
+
private parseFragment;
|
|
137
|
+
private applyLineMode;
|
|
138
|
+
private closeAllTags;
|
|
139
|
+
private handleTag;
|
|
140
|
+
private openAllowed;
|
|
141
|
+
private handleOpenTag;
|
|
142
|
+
/** `<FRAME name [action] [internal|external|floating] [left|top|width|height]
|
|
143
|
+
* [scrolling] [title]>` — record a window create/close request for the
|
|
144
|
+
* consumer. NAME is the first positional or the NAME attribute; valueless
|
|
145
|
+
* flags (INTERNAL/EXTERNAL/FLOATING) become `"true"`. */
|
|
146
|
+
private handleFrameTag;
|
|
147
|
+
/** `<DEST name [eol] [eof]>` — start redirecting enclosed text into `name`.
|
|
148
|
+
* NAME is the NAME attribute or the first non-flag positional. Persists
|
|
149
|
+
* until `</DEST>` (or end of line). A nameless DEST is ignored so its text
|
|
150
|
+
* renders inline, matching Mudlet (setMxpDestination fails → not handled). */
|
|
151
|
+
private handleDestTag;
|
|
152
|
+
/** `<SOUND fname [V=vol] [L=loops] [P=priority] [T=type] [U=url]>` and
|
|
153
|
+
* `<MUSIC fname [V=vol] [L=loops] [C=continue] [T=type] [U=url]>` — MXP's
|
|
154
|
+
* audio triggers (https://www.zuggsoft.com/zmud/mxp.htm#Sound). They carry
|
|
155
|
+
* the same fields as MSP's `!!SOUND`/`!!MUSIC`, so surface them as an
|
|
156
|
+
* {@link MspCommand} and let the consumer route them through the same
|
|
157
|
+
* SoundManager path. FNAME is the FNAME attribute or the first positional;
|
|
158
|
+
* the literal `Off` (also `off`) stops playback. A fileless tag is ignored. */
|
|
159
|
+
private handleSoundTag;
|
|
160
|
+
/** Finalize the current `<DEST>` run into a redirect and stop redirecting. */
|
|
161
|
+
private closeDest;
|
|
162
|
+
private openFormat;
|
|
163
|
+
private openColor;
|
|
164
|
+
private openLink;
|
|
165
|
+
private openVar;
|
|
166
|
+
private handleCloseTag;
|
|
167
|
+
private finalizeTag;
|
|
168
|
+
private handleDefinition;
|
|
169
|
+
private defineElement;
|
|
170
|
+
private defineEntity;
|
|
171
|
+
private expandElement;
|
|
172
|
+
private substituteTemplate;
|
|
173
|
+
private decodeEntity;
|
|
174
|
+
}
|
|
175
|
+
/** Split a parsed MXP line into one entry per *visual* line. MXP `<BR>` tags
|
|
176
|
+
* become embedded `\n`s in the parser's plain text and segments — Discworld
|
|
177
|
+
* sends a whole room (description, exits, contents, prompt) as a single network
|
|
178
|
+
* line delimited by `<BR>` — but a render path that emits one line per result
|
|
179
|
+
* would collapse them all together. So we split the segments at every `\n`,
|
|
180
|
+
* re-slicing each segment's text and remapping each link's `plain`-offset range
|
|
181
|
+
* into the subline it falls on. The `\n` separators are dropped (each subline
|
|
182
|
+
* renders on its own). The fast path (no embedded newline) returns the result
|
|
183
|
+
* untouched, sharing the original arrays. */
|
|
184
|
+
export declare function splitMxpResultLines(r: MxpLineResult): {
|
|
185
|
+
plain: string;
|
|
186
|
+
segments: BufferSegment[];
|
|
187
|
+
links: MxpLink[];
|
|
188
|
+
}[];
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Frame an `IAC SB NAWS <width> <height> IAC SE` subnegotiation (telnet option
|
|
3
|
+
* 31, RFC 1073) reporting the client window size as character columns × rows.
|
|
4
|
+
* Both dimensions are 16-bit big-endian, clamped to [0, 65535], with IAC bytes
|
|
5
|
+
* escaped. The returned string is a Latin-1 byte-string ready for sendRaw.
|
|
6
|
+
*/
|
|
7
|
+
export declare function encodeNaws(cols: number, rows: number): string;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type ReplayChunk } from './replayFormat';
|
|
2
|
+
export interface ReplayPlayerCallbacks {
|
|
3
|
+
/** Current playback speed divisor (1 = real time). Read at each chunk's
|
|
4
|
+
* schedule time, so mid-replay speed changes affect subsequent chunks —
|
|
5
|
+
* matching Mudlet's `offset / mReplaySpeed` singleShot scheduling. */
|
|
6
|
+
speed: () => number;
|
|
7
|
+
/** Deliver one chunk's bytes (as a Latin-1 byte-string) to the inbound
|
|
8
|
+
* telnet pipeline. */
|
|
9
|
+
feed: (data: string) => void;
|
|
10
|
+
/** Fired once, after the last chunk has been delivered. Not fired on abort. */
|
|
11
|
+
onDone: () => void;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Plays parsed replay chunks back on their recorded timeline: each chunk is
|
|
15
|
+
* scheduled `offsetMs / speed` after the previous one and fed into the telnet
|
|
16
|
+
* parsing pipeline, so triggers, GMCP handlers, and rendering all behave as
|
|
17
|
+
* they did live.
|
|
18
|
+
*/
|
|
19
|
+
export declare class ReplayPlayer {
|
|
20
|
+
private readonly chunks;
|
|
21
|
+
private readonly callbacks;
|
|
22
|
+
private timer;
|
|
23
|
+
private index;
|
|
24
|
+
private finished;
|
|
25
|
+
constructor(chunks: ReplayChunk[], callbacks: ReplayPlayerCallbacks);
|
|
26
|
+
start(): void;
|
|
27
|
+
/** Stop playback and drop any pending chunk. Idempotent; onDone is not
|
|
28
|
+
* fired for an aborted replay. */
|
|
29
|
+
abort(): void;
|
|
30
|
+
private scheduleNext;
|
|
31
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Accumulates the inbound telnet stream into Mudlet replay chunks. Fed with
|
|
3
|
+
* the post-MCCP Latin-1 byte-strings the client emits as `socket.incoming` —
|
|
4
|
+
* the same tap point Mudlet records at, so the file captures IAC sequences,
|
|
5
|
+
* GMCP subnegotiations, prompts, and ANSI verbatim. Chunks are buffered in
|
|
6
|
+
* memory (MUD output is small) and serialized once on stop().
|
|
7
|
+
*/
|
|
8
|
+
export declare class ReplayRecorder {
|
|
9
|
+
private chunks;
|
|
10
|
+
private lastChunkTime;
|
|
11
|
+
constructor();
|
|
12
|
+
/** Record one inbound data block. The chunk's offset is the time elapsed
|
|
13
|
+
* since the previous block (or since recording started, for the first). */
|
|
14
|
+
feed(data: string): void;
|
|
15
|
+
get chunkCount(): number;
|
|
16
|
+
/** Serialize everything recorded so far to Mudlet's .dat format. */
|
|
17
|
+
encode(): Uint8Array;
|
|
18
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mudlet binary replay (".dat") format — the files written by Mudlet's
|
|
3
|
+
* "record replay" toolbar button and consumed by its `loadReplay()`.
|
|
4
|
+
*
|
|
5
|
+
* The on-disk layout is a bare sequence of chunk records with no header:
|
|
6
|
+
*
|
|
7
|
+
* int32 BE offsetMs milliseconds elapsed since the previous chunk
|
|
8
|
+
* int32 BE length payload byte count (1..REPLAY_MAX_CHUNK)
|
|
9
|
+
* bytes payload the network data verbatim — post-MCCP-decompression,
|
|
10
|
+
* pre-telnet-parsing, IAC sequences and all
|
|
11
|
+
*
|
|
12
|
+
* Qt's QDataStream defaults to big-endian, and Mudlet only ever streams
|
|
13
|
+
* qint32s + raw bytes, so this is the complete format. One historical quirk:
|
|
14
|
+
* Mudlet PR #4400 accidentally widened the offset to a qint64 for some
|
|
15
|
+
* releases (the "modified format"); Mudlet's loader trial-parses the original
|
|
16
|
+
* layout first and falls back, and parseReplay mirrors that so both vintages
|
|
17
|
+
* load. We always *write* the original format — what current Mudlet records.
|
|
18
|
+
*/
|
|
19
|
+
export interface ReplayChunk {
|
|
20
|
+
/** Milliseconds since the previous chunk (recording start for the first). */
|
|
21
|
+
offsetMs: number;
|
|
22
|
+
/** Raw telnet bytes as received post-MCCP. */
|
|
23
|
+
data: Uint8Array;
|
|
24
|
+
}
|
|
25
|
+
/** Mudlet's replay read buffer size (cTelnet BUFFER_SIZE). A record whose
|
|
26
|
+
* length field exceeds this is treated as corrupt by Mudlet's loader, so the
|
|
27
|
+
* encoder splits bigger payloads into continuation records (offset 0). */
|
|
28
|
+
export declare const REPLAY_MAX_CHUNK = 100000;
|
|
29
|
+
/** Latin-1 byte-string (charCode === byte) → bytes, the inverse of
|
|
30
|
+
* {@link replayBytesToLatin1}. The telnet pipeline traffics in these strings. */
|
|
31
|
+
export declare function replayLatin1ToBytes(data: string): Uint8Array;
|
|
32
|
+
/** Bytes → Latin-1 byte-string, chunked to respect String.fromCharCode's
|
|
33
|
+
* argument limit on large payloads (same trick as MudClient's frame decode). */
|
|
34
|
+
export declare function replayBytesToLatin1(bytes: Uint8Array): string;
|
|
35
|
+
/** Serialize chunks to the original (current-Mudlet) replay format. Payloads
|
|
36
|
+
* larger than {@link REPLAY_MAX_CHUNK} are split into continuation records
|
|
37
|
+
* with a 0ms offset so Mudlet itself can read the file back. Empty payloads
|
|
38
|
+
* are dropped — Mudlet's loader treats a 0-length record as corruption. */
|
|
39
|
+
export declare function encodeReplay(chunks: ReplayChunk[]): Uint8Array;
|
|
40
|
+
/** Parse a replay file, auto-detecting the original (4-byte offset) vs the
|
|
41
|
+
* modified (8-byte offset, PR #4400 era) layout the way Mudlet's
|
|
42
|
+
* testReadReplayFile does: trial-parse original first, fall back to modified.
|
|
43
|
+
* Returns null when the data is readable as neither — "seems to be corrupt". */
|
|
44
|
+
export declare function parseReplay(bytes: Uint8Array): ReplayChunk[] | null;
|
|
45
|
+
/** Total recorded duration in milliseconds (sum of chunk offsets). */
|
|
46
|
+
export declare function replayDurationMs(chunks: ReplayChunk[]): number;
|
|
47
|
+
/** Mudlet-style replay file name for a recording finished at `date`:
|
|
48
|
+
* `yyyy-MM-dd#HH-mm-ss.dat`, e.g. `2026-07-08#14-03-59.dat`. */
|
|
49
|
+
export declare function replayFileName(date: Date): string;
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { FormatState } from './FormatState';
|
|
2
|
+
import { AnsiAwareBuffer } from './FormatState';
|
|
3
|
+
import type { FormatStateSnapshot } from './FormatState';
|
|
4
|
+
/**
|
|
5
|
+
* Self-contained text output entity — equivalent of Mudlet's TConsole.
|
|
6
|
+
* Owns format state, line history, and cursor position.
|
|
7
|
+
* The renderer is a pure consumer: it receives lines via takeLines() and
|
|
8
|
+
* calls buf.notifyRender() so that rerender()/removeFromDom() can reach the DOM.
|
|
9
|
+
*/
|
|
10
|
+
export declare class Console {
|
|
11
|
+
readonly format: FormatState;
|
|
12
|
+
private history;
|
|
13
|
+
private pending;
|
|
14
|
+
private partial;
|
|
15
|
+
private cursorIdx;
|
|
16
|
+
private cursorCol;
|
|
17
|
+
private _maxLines;
|
|
18
|
+
private _batchDeleteSize;
|
|
19
|
+
/** Mudlet `sysBufferShrinkEvent(name, linesRemoved)` hook. Fired by
|
|
20
|
+
* `evict()` whenever the scrollback cap drops one or more lines from the
|
|
21
|
+
* head of `history`. Set by the owning session (ScriptingAPI for "main",
|
|
22
|
+
* WindowManager for named user windows). */
|
|
23
|
+
onBufferShrink: ((linesRemoved: number) => void) | undefined;
|
|
24
|
+
private consumeLeadingNewline;
|
|
25
|
+
setFgColor(r: number, g: number, b: number): void;
|
|
26
|
+
setBgColor(r: number, g: number, b: number, a?: number): void;
|
|
27
|
+
setBold(v: boolean): void;
|
|
28
|
+
setItalic(v: boolean): void;
|
|
29
|
+
setUnderline(v: boolean): void;
|
|
30
|
+
setStrikethrough(v: boolean): void;
|
|
31
|
+
setOverline(v: boolean): void;
|
|
32
|
+
setReverse(v: boolean): void;
|
|
33
|
+
resetFormat(): void;
|
|
34
|
+
get maxLines(): number;
|
|
35
|
+
setMaxLines(n: number): void;
|
|
36
|
+
get batchDeleteSize(): number;
|
|
37
|
+
setBatchDeleteSize(n: number): void;
|
|
38
|
+
echo(text: string): void;
|
|
39
|
+
/**
|
|
40
|
+
* Append a pre-built complete line buffer to history. Used by the network
|
|
41
|
+
* trigger pipeline: the line has already been parsed and is being added as
|
|
42
|
+
* a single canonical entry, not via partial accumulation. The cursor is
|
|
43
|
+
* placed on the new line at column 0 so triggers see Mudlet's "cursor on
|
|
44
|
+
* the matching line at trigger fire" state. Does NOT enqueue into pending
|
|
45
|
+
* — the renderer for network output drains via the 'message' event
|
|
46
|
+
* pipeline; pending is reserved for script-driven echo flushes.
|
|
47
|
+
*/
|
|
48
|
+
appendLine(buffer: AnsiAwareBuffer): void;
|
|
49
|
+
/**
|
|
50
|
+
* Append a pre-formatted buffer as a new complete line — mirrors Mudlet's
|
|
51
|
+
* TConsole::appendBuffer, the primitive behind the `appendBuffer`/`paste`
|
|
52
|
+
* clipboard functions. Unlike `appendLine` (network pipeline) this also
|
|
53
|
+
* enqueues into `pending` so the line reaches the renderer through the
|
|
54
|
+
* normal drain path; the cursor resets to the end so a following
|
|
55
|
+
* `selectCurrentLine` sees the pasted line.
|
|
56
|
+
*/
|
|
57
|
+
appendBuffer(buffer: AnsiAwareBuffer): void;
|
|
58
|
+
private evict;
|
|
59
|
+
/** Drain newly completed lines to hand to the renderer. */
|
|
60
|
+
takeLines(): AnsiAwareBuffer[];
|
|
61
|
+
get currentPartial(): AnsiAwareBuffer;
|
|
62
|
+
/**
|
|
63
|
+
* Promote the in-flight partial (an echo without a trailing newline, e.g.
|
|
64
|
+
* a trigger's `cecho("\n text")`) into a finished history line and return
|
|
65
|
+
* it, leaving a fresh empty partial behind. Returns null when nothing is
|
|
66
|
+
* pending. Unlike `clear()`, the existing history is preserved so
|
|
67
|
+
* line-number / selectString lookups for later lines in the same flush
|
|
68
|
+
* batch stay valid — this is what lets a per-line trigger-echo flush place
|
|
69
|
+
* the echoed line right after the line it was echoed on. The line is NOT
|
|
70
|
+
* enqueued into `pending` (the caller emits it explicitly), so a following
|
|
71
|
+
* `takeLines()` won't re-emit it.
|
|
72
|
+
*/
|
|
73
|
+
completePartialLine(): AnsiAwareBuffer | null;
|
|
74
|
+
clear(): void;
|
|
75
|
+
/**
|
|
76
|
+
* Discard only the in-flight partial (and the leading-newline latch),
|
|
77
|
+
* leaving history/cursor untouched. `feedTriggers` uses this to drop a
|
|
78
|
+
* stray partial left by a prior direct `echo()` without wiping accumulated
|
|
79
|
+
* history — multiple `feedTriggers` calls must accumulate lines (Mudlet
|
|
80
|
+
* appends fed text to the buffer), which a full `clear()` would destroy.
|
|
81
|
+
*/
|
|
82
|
+
clearPartial(): void;
|
|
83
|
+
private get cursor();
|
|
84
|
+
private get followingEnd();
|
|
85
|
+
getLine(): string;
|
|
86
|
+
getBuffer(): AnsiAwareBuffer | null;
|
|
87
|
+
/** Per-line prompt flag on the current cursor line. Mirrors Mudlet's TBuffer
|
|
88
|
+
* behaviour: `isPrompt()` follows the cursor, so moveCursor + isPrompt can
|
|
89
|
+
* inspect any historical line's prompt status, not just the most recent. */
|
|
90
|
+
cursorOnPrompt(): boolean;
|
|
91
|
+
deleteLine(): void;
|
|
92
|
+
/**
|
|
93
|
+
* Insert `text` at the cursor (Mudlet `insertText`). Embedded `\n` split the
|
|
94
|
+
* current line into multiple history lines (Mudlet issue #8945): the text up
|
|
95
|
+
* to the first `\n` is inserted at the cursor column, each subsequent `\n`
|
|
96
|
+
* starts a new line, and the remainder of the original line trails the last
|
|
97
|
+
* inserted segment. For a single-line insert the cursor stays at the
|
|
98
|
+
* insertion point (Mudlet's `insertText` does not advance `mUserCursor` — the
|
|
99
|
+
* bundled GUIUtils `xEcho`/`cinsertText` loop advances it explicitly with its
|
|
100
|
+
* own `moveCursor` after each segment; advancing here too would double-count
|
|
101
|
+
* and push later color segments past their intended column). Returns false
|
|
102
|
+
* when there's no current line to insert into (caller falls back to an echo).
|
|
103
|
+
* Mid-buffer multi-line inserts update the buffer model fully; the
|
|
104
|
+
* incremental renderer redraws the affected line(s) lazily.
|
|
105
|
+
*/
|
|
106
|
+
insertText(text: string, state?: FormatStateSnapshot): boolean;
|
|
107
|
+
/**
|
|
108
|
+
* Move the cursor up `lines` rows. When `keepHorizontal` is false (the
|
|
109
|
+
* default, matching Mudlet) the column resets to 0; when true the column
|
|
110
|
+
* is preserved across the move and lazily clamps to the destination
|
|
111
|
+
* line's length on read via `getCursorColumn`.
|
|
112
|
+
*/
|
|
113
|
+
moveUp(lines?: number, keepHorizontal?: boolean): boolean;
|
|
114
|
+
moveDown(lines?: number, keepHorizontal?: boolean): boolean;
|
|
115
|
+
/**
|
|
116
|
+
* Seek the cursor to absolute line `line` (0-indexed). When `col` is
|
|
117
|
+
* supplied, also set the column; otherwise the column is reset to 0 (the
|
|
118
|
+
* Mudlet `moveCursor(x=0, y)` default).
|
|
119
|
+
*/
|
|
120
|
+
moveTo(line: number, col?: number): boolean;
|
|
121
|
+
/**
|
|
122
|
+
* Mudlet's `mUserCursor.x()` — the column on the cursor line. Lazily
|
|
123
|
+
* clamped to the current line's length so a stale `cursorCol` from a
|
|
124
|
+
* `keepHorizontal` move never reports past the end of a shorter line.
|
|
125
|
+
*/
|
|
126
|
+
getCursorColumn(): number;
|
|
127
|
+
setCursorColumn(col: number): boolean;
|
|
128
|
+
/** Mark cursor as positioned at the end of existing rendered content, so the
|
|
129
|
+
* next leading `\n` is treated as cursor advance rather than a blank line.
|
|
130
|
+
* Pass `false` to clear the latch (e.g. when leaving trigger processing) so
|
|
131
|
+
* it can't leak onto an unrelated later echo. */
|
|
132
|
+
markCursorAtEnd(value?: boolean): void;
|
|
133
|
+
getLineNumber(): number;
|
|
134
|
+
getLineCount(): number;
|
|
135
|
+
/**
|
|
136
|
+
* Mudlet `moveCursorEnd` — park the cursor on the empty line past the last
|
|
137
|
+
* complete one, which is where Mudlet's buffer always keeps its "current"
|
|
138
|
+
* entry (so `getLineNumber() == getLineCount()` right after). That slot is
|
|
139
|
+
* one past `history`, which {@link moveTo} deliberately refuses, so it is
|
|
140
|
+
* set here rather than routed through it.
|
|
141
|
+
*/
|
|
142
|
+
moveToEnd(): void;
|
|
143
|
+
/**
|
|
144
|
+
* Mudlet `getLines(from, to)` — the lines starting at the 0-based index
|
|
145
|
+
* `from`, `abs(to - from)` of them (TConsole::getLines). Note that `to` is
|
|
146
|
+
* exclusive and that neither bound is clamped by Mudlet; out-of-range
|
|
147
|
+
* indices simply yield fewer lines here.
|
|
148
|
+
*/
|
|
149
|
+
getLines(from: number, to: number): string[];
|
|
150
|
+
/**
|
|
151
|
+
* Mudlet `getTimestamp(lineNumber)` — the wall-clock time (epoch ms) the
|
|
152
|
+
* line entered the buffer. `lineNumber` is 1-based to match `getLines`
|
|
153
|
+
* (Mudlet's timeBuffer reserves index 0); omit it to read the current
|
|
154
|
+
* cursor line. Returns null when the line is out of range or the buffer
|
|
155
|
+
* is empty. Formatting into Mudlet's "hh:mm:ss.zzz" string happens one
|
|
156
|
+
* layer up, in ScriptingAPI.
|
|
157
|
+
*/
|
|
158
|
+
getLineTimestamp(lineNumber?: number): number | null;
|
|
159
|
+
/**
|
|
160
|
+
* Mudlet `wrapLine(lineNumber)` — re-display the line at `lineNumber`
|
|
161
|
+
* (0-indexed, matching getLineNumber/getLineCount), re-interpreting its
|
|
162
|
+
* embedded `\n` characters and re-wrapping to the current width. mudix
|
|
163
|
+
* renders each line buffer with CSS `white-space: pre-wrap`, and the
|
|
164
|
+
* rendered DOM node holds the very same buffer object as history (set via
|
|
165
|
+
* `notifyRender`), so re-rendering that buffer in place is what makes any
|
|
166
|
+
* `\n` show as line breaks — the documented use case after a `deleteLine()`
|
|
167
|
+
* + `echo()` sequence left un-displayed newlines in the buffer. Returns
|
|
168
|
+
* false when `lineNumber` is out of range.
|
|
169
|
+
*/
|
|
170
|
+
/**
|
|
171
|
+
* Mudlet `wrapLine(lineNumber)` — re-wrap one stored line to the console's
|
|
172
|
+
* current wrap width, replacing it with as many buffer lines as it now
|
|
173
|
+
* needs. That is a real buffer edit in Mudlet (TBuffer::wrapLine splits the
|
|
174
|
+
* line in place), not a repaint: getLineCount and getLines see the split
|
|
175
|
+
* afterwards.
|
|
176
|
+
*
|
|
177
|
+
* `wrapAt` of 0 (wrapping disabled) leaves the line alone and just
|
|
178
|
+
* repaints. `indent` prefixes the first resulting line and `hangingIndent`
|
|
179
|
+
* every continuation, matching setWindowWrapIndent /
|
|
180
|
+
* setWindowWrapHangingIndent.
|
|
181
|
+
*/
|
|
182
|
+
wrapLine(lineNumber: number, wrapAt?: number, indent?: number, hangingIndent?: number): boolean;
|
|
183
|
+
}
|