@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,268 @@
|
|
|
1
|
+
import { EventBus } from "../../core/EventBus";
|
|
2
|
+
import { AnsiAwareBuffer } from "../text/FormatState";
|
|
3
|
+
import { type ChunkProcessor } from "../triggers/ChunkProcessor";
|
|
4
|
+
import type { MudClientEvents } from "../events";
|
|
5
|
+
export type { MudClientEvents } from "../events";
|
|
6
|
+
export { SUPPORTED_SERVER_ENCODINGS } from "../protocol";
|
|
7
|
+
export interface MudClientOptions {
|
|
8
|
+
url: string;
|
|
9
|
+
mccpEnabled?: boolean;
|
|
10
|
+
commandEcho?: boolean;
|
|
11
|
+
chunkProcessor?: ChunkProcessor;
|
|
12
|
+
/** Milliseconds to hold a partial trailing line (text after the last `\n`)
|
|
13
|
+
* before flushing it as a prompt. Mirrors Mudlet's "Network packet timeout"
|
|
14
|
+
* preference; defaults to 300ms. Once a server has sent IAC GA or IAC EOR
|
|
15
|
+
* at least once, the client latches into "GA-driver" mode and the partial
|
|
16
|
+
* tail is flushed by the prompt marker instead of this timer — so the value
|
|
17
|
+
* only matters as an idle safety net (e.g. a line split across frames whose
|
|
18
|
+
* remainder never arrives). */
|
|
19
|
+
promptTimeoutMs?: number;
|
|
20
|
+
/** Whether to accept GMCP (telnet option 201) negotiation. Default true.
|
|
21
|
+
* When false, the client silently ignores IAC WILL/DO GMCP so the server
|
|
22
|
+
* never sees a positive ack and no GMCP envelopes flow. */
|
|
23
|
+
gmcpEnabled?: boolean;
|
|
24
|
+
/** Whether to accept TERMINAL-TYPE / MTTS (telnet option 24) negotiation.
|
|
25
|
+
* Default true. When false, IAC DO TTYPE is ignored so the server falls
|
|
26
|
+
* back to its non-MTTS code path. */
|
|
27
|
+
mttsEnabled?: boolean;
|
|
28
|
+
/** Whether to accept MSDP (telnet option 69) negotiation. Default false.
|
|
29
|
+
* When false, IAC WILL/DO MSDP is ignored and no MSDP envelopes flow. */
|
|
30
|
+
msdpEnabled?: boolean;
|
|
31
|
+
/** Whether to accept MSSP (telnet option 70) negotiation. Default true
|
|
32
|
+
* (matching Mudlet). When false, IAC WILL/DO MSSP is ignored and the
|
|
33
|
+
* server's status subnegotiation never arrives. */
|
|
34
|
+
msspEnabled?: boolean;
|
|
35
|
+
/** Whether to accept CHARSET (telnet option 42, RFC 2066) negotiation.
|
|
36
|
+
* Default true. When false, IAC WILL/DO CHARSET is ignored and the
|
|
37
|
+
* session stays on the UTF-8 baseline (so non-ASCII bytes from non-UTF-8
|
|
38
|
+
* MUDs render as replacement chars). */
|
|
39
|
+
charsetEnabled?: boolean;
|
|
40
|
+
/** Whether to enable MSP (MUD Sound Protocol, telnet option 90). Default
|
|
41
|
+
* false. When true the client negotiates the option and strips inline
|
|
42
|
+
* `!!SOUND(...)` / `!!MUSIC(...)` tags from MUD text, dispatching them
|
|
43
|
+
* as `msp` events. Always parses subnegotiations regardless of this flag
|
|
44
|
+
* once negotiated, but in-band parsing is gated to avoid eating literal
|
|
45
|
+
* text on MUDs that don't speak MSP. */
|
|
46
|
+
mspEnabled?: boolean;
|
|
47
|
+
/** Whether to accept MXP (telnet option 91) negotiation. Default true.
|
|
48
|
+
* When false, IAC WILL/DO MXP is ignored so the server never sees a
|
|
49
|
+
* positive ack and no in-band MXP markup is parsed (tags pass through as
|
|
50
|
+
* literal text). The actual tag parsing lives downstream in the scripting
|
|
51
|
+
* engine, gated on the `mxp.negotiated` event this client emits. */
|
|
52
|
+
mxpEnabled?: boolean;
|
|
53
|
+
/** Whether to answer telnet option 39 in MNES mode (Mud New-Environ
|
|
54
|
+
* Standard). Default false. When on, the client reports the five MNES core
|
|
55
|
+
* variables (CHARSET / CLIENT_NAME / CLIENT_VERSION / MTTS / TERMINAL_TYPE),
|
|
56
|
+
* framed as NEW_ENVIRON_VAR. MNES takes precedence over plain NEW-ENVIRON
|
|
57
|
+
* when both are enabled — matching Mudlet, which restricts the reported set
|
|
58
|
+
* to these five whenever MNES is active. */
|
|
59
|
+
mnesEnabled?: boolean;
|
|
60
|
+
/** Whether to answer telnet option 39 in plain NEW-ENVIRON mode (RFC 1572,
|
|
61
|
+
* "Client Variables Standard"). Default false. When on (and MNES off), the
|
|
62
|
+
* client reports the five core variables plus an extended capability set
|
|
63
|
+
* (ANSI, 256_COLORS, TRUECOLOR, UTF-8, TLS, WORD_WRAP, …), framed as
|
|
64
|
+
* NEW_ENVIRON_USERVAR. Mudlet exposes MNES and NEW-ENVIRON as two separate
|
|
65
|
+
* toggles over the same telnet option; mudix mirrors that. */
|
|
66
|
+
newEnvironEnabled?: boolean;
|
|
67
|
+
/** Whether the link to the *game server* is TLS-encrypted, reported as the
|
|
68
|
+
* NEW-ENVIRON `TLS` capability. Defaults to whether `url` is `wss://` — the
|
|
69
|
+
* correct answer for a direct websocket-mode connection. In proxy (`mud`)
|
|
70
|
+
* mode the caller passes `false` explicitly, because a `wss://` proxy URL
|
|
71
|
+
* only secures the browser↔proxy hop while the proxy↔MUD telnet socket is
|
|
72
|
+
* plaintext (see connectionSecureTransport). */
|
|
73
|
+
secureTransport?: boolean;
|
|
74
|
+
/** Whether to advertise screen-reader use, reported as the MTTS SCREEN
|
|
75
|
+
* READER bit and the NEW-ENVIRON `SCREEN_READER` capability
|
|
76
|
+
* (`setConfig("advertiseScreenReader", …)`). Default false. */
|
|
77
|
+
screenReaderAdvertised?: boolean;
|
|
78
|
+
/** Whether to negotiate NAWS / window size (telnet option 31). Default true
|
|
79
|
+
* (matching Mudlet). When true the client offers IAC WILL NAWS on connect
|
|
80
|
+
* and, once the server accepts (IAC DO NAWS), reports the main output
|
|
81
|
+
* area's character grid (columns × rows) and re-sends it on every resize.
|
|
82
|
+
* When false the client never offers NAWS and ignores IAC DO NAWS. */
|
|
83
|
+
nawsEnabled?: boolean;
|
|
84
|
+
/** Mudlet's "Fix unnecessary linebreaks on GA servers"
|
|
85
|
+
* (`setConfig("fixUnnecessaryLinebreaks", …)`, host flag
|
|
86
|
+
* `mUSE_IRE_DRIVER_BUGFIX`). Default false. When true *and* the session is
|
|
87
|
+
* GA-driven, a single spurious leading newline is stripped from the start
|
|
88
|
+
* of each GA-terminated data block — the IRE-server bug Mudlet patches in
|
|
89
|
+
* `cTelnet::gotPrompt`. See LineAssembler. */
|
|
90
|
+
fixUnnecessaryLinebreaks?: boolean;
|
|
91
|
+
/** WebSocket subprotocols to advertise in the opening handshake's
|
|
92
|
+
* `Sec-WebSocket-Protocol` header (RFC 6455), in preference order — the
|
|
93
|
+
* server selects at most one. Mutually-exclusive stream *modes*, not layers:
|
|
94
|
+
* `binary` (raw telnet over binary frames — the mode mudix decodes),
|
|
95
|
+
* `telnet` (FluffOS's equivalent name), `telnet.mudstandards.org` (the
|
|
96
|
+
* mudstandards.org proposal). Empty means open a bare socket. Advertising is
|
|
97
|
+
* a trade-off: some servers (FluffOS) route a *no-subprotocol* upgrade to a
|
|
98
|
+
* non-MUD handler and never send data, while others (e.g. last-outpost.com)
|
|
99
|
+
* *reject* an unrecognized subprotocol with HTTP 400 — hence the per-profile
|
|
100
|
+
* choice. The server's selection is read back from `socket.protocol` on open
|
|
101
|
+
* and emitted via `client.subprotocol`. */
|
|
102
|
+
subprotocols?: string[];
|
|
103
|
+
}
|
|
104
|
+
/** The WebSocket subprotocol name for the mudstandards.org "full telnet stream
|
|
105
|
+
* over binary frames" profile (https://mudstandards.org/websocket/). mudix
|
|
106
|
+
* already speaks this wire format; advertising the name lets a conforming
|
|
107
|
+
* server confirm the dialect via the RFC 6455 handshake. */
|
|
108
|
+
export declare const MUD_TELNET_SUBPROTOCOL = "telnet.mudstandards.org";
|
|
109
|
+
/**
|
|
110
|
+
* The MUD-facing transport: telnet over a WebSocket (direct or via the
|
|
111
|
+
* telnet→WebSocket proxy). Owns the socket lifecycle and the outbound send
|
|
112
|
+
* paths; the protocol concerns are composed from dedicated pieces —
|
|
113
|
+
* {@link TelnetNegotiator} (option negotiation + sysTelnetEvent),
|
|
114
|
+
* {@link SessionCodec}/{@link CharsetHandler} (byte↔char encoding + CHARSET),
|
|
115
|
+
* {@link LineAssembler} (partial-line buffering + prompt flushing),
|
|
116
|
+
* `MccpHandler` (compression), `EchoHandler` (password masking), and the
|
|
117
|
+
* GMCP/MSDP/MSSP subnegotiation streams.
|
|
118
|
+
*/
|
|
119
|
+
export declare class MudClient {
|
|
120
|
+
private socket;
|
|
121
|
+
private readonly eventBus;
|
|
122
|
+
private readonly chunkProcessor;
|
|
123
|
+
private messageBuffer;
|
|
124
|
+
private readonly gmcpStream;
|
|
125
|
+
private readonly msdpStream;
|
|
126
|
+
private readonly msspStream;
|
|
127
|
+
private readonly telnetOptionHandler;
|
|
128
|
+
private readonly mccpHandler;
|
|
129
|
+
private readonly echoHandler;
|
|
130
|
+
private readonly negotiator;
|
|
131
|
+
/** Latches once `sysCharacterModeDetected` has fired for this connection so
|
|
132
|
+
* the warning isn't repeated. Reset on each connect(). See
|
|
133
|
+
* {@link maybeDetectCharacterMode}. */
|
|
134
|
+
private charModeDetected;
|
|
135
|
+
/** Byte↔char codec for the session (inbound streaming decoder + outgoing
|
|
136
|
+
* encoding). Swapped between encodings by the CHARSET handler. */
|
|
137
|
+
private readonly codec;
|
|
138
|
+
private readonly charsetHandler;
|
|
139
|
+
/** Whole-line assembly of the decoded text stream (partial-tail buffering,
|
|
140
|
+
* GA-driven prompt flushing, the idle-flush safety net). */
|
|
141
|
+
private readonly assembler;
|
|
142
|
+
private readonly url;
|
|
143
|
+
/** Buffers the start of a subnegotiation that arrived without its closing IAC SE. */
|
|
144
|
+
private pendingSubneg;
|
|
145
|
+
/** True once the WebSocket handshake has completed; used to differentiate
|
|
146
|
+
* "failed to connect" from "connection lost mid-session" in close events. */
|
|
147
|
+
private opened;
|
|
148
|
+
/** True once we've sent the GMCP `Core.Hello` / `Core.Supports.Set`
|
|
149
|
+
* handshake this session, so a server that re-offers GMCP doesn't make us
|
|
150
|
+
* announce ourselves twice. Reset on each connect(). */
|
|
151
|
+
private gmcpHelloSent;
|
|
152
|
+
commandEcho: boolean;
|
|
153
|
+
/** Gates the in-band `!!SOUND(...)` / `!!MUSIC(...)` tag parsing — the tag
|
|
154
|
+
* bytes are legitimate text on non-MSP MUDs. */
|
|
155
|
+
private readonly mspEnabled;
|
|
156
|
+
private readonly mspParser;
|
|
157
|
+
/** WebSocket subprotocols advertised on connect (see MudClientOptions). */
|
|
158
|
+
private readonly subprotocols;
|
|
159
|
+
constructor({ url, mccpEnabled, commandEcho, chunkProcessor, promptTimeoutMs, gmcpEnabled, mttsEnabled, msdpEnabled, msspEnabled, charsetEnabled, mspEnabled, mxpEnabled, mnesEnabled, newEnvironEnabled, secureTransport, screenReaderAdvertised, nawsEnabled, fixUnnecessaryLinebreaks, subprotocols, }: MudClientOptions, eventBus: EventBus<MudClientEvents>);
|
|
160
|
+
/** Mudlet-parity character-at-a-time detection (cTelnet::
|
|
161
|
+
* checkCharacterModePattern). When the server has both asked to suppress
|
|
162
|
+
* go-ahead (IAC WILL SGA — which we refuse) *and* enabled server-side echo,
|
|
163
|
+
* it's driving a character-at-a-time session that mudix, a line-based
|
|
164
|
+
* client, can't handle well. Raise `sysCharacterModeDetected` once so the
|
|
165
|
+
* UI / scripts can warn the user. Checked on both trigger edges: an SGA
|
|
166
|
+
* request arriving while echo is already on, and echo committing while SGA
|
|
167
|
+
* was already requested. */
|
|
168
|
+
private maybeDetectCharacterMode;
|
|
169
|
+
setMccpEnabled(enabled: boolean): void;
|
|
170
|
+
isMccpEnabled(): boolean;
|
|
171
|
+
/** Mudlet `setConfig("fixUnnecessaryLinebreaks", …)`. Takes effect on the
|
|
172
|
+
* next GA-driven block; never retroactive. */
|
|
173
|
+
setFixUnnecessaryLinebreaks(enabled: boolean): void;
|
|
174
|
+
/** Mudlet `addSupportedTelnetOption(option)`. See TelnetNegotiator. */
|
|
175
|
+
addSupportedTelnetOption(option: number): boolean;
|
|
176
|
+
setPromptTimeoutMs(ms: number): void;
|
|
177
|
+
getPromptTimeoutMs(): number;
|
|
178
|
+
connect(): void;
|
|
179
|
+
disconnect(): void;
|
|
180
|
+
/** Whether MSP is live on this connection (negotiated, not merely allowed
|
|
181
|
+
* by the profile config) — gates Mudlet's receiveMSP. */
|
|
182
|
+
isMspNegotiated(): boolean;
|
|
183
|
+
/** Qt's QAbstractSocket::UnconnectedState — no socket at all, or one that
|
|
184
|
+
* has finished closing. CONNECTING/OPEN/CLOSING are all "not unconnected",
|
|
185
|
+
* which is the state feedTelnet refuses to inject into. */
|
|
186
|
+
isSocketUnconnected(): boolean;
|
|
187
|
+
isSocketOpen(): boolean;
|
|
188
|
+
isPasswordMode(): boolean;
|
|
189
|
+
shouldEchoCommand(): boolean;
|
|
190
|
+
send(message: string): void;
|
|
191
|
+
private sendRaw;
|
|
192
|
+
/** Encodes a Latin-1 byte-string to raw bytes and sends it as a binary
|
|
193
|
+
* WebSocket frame. The proxy worker expects binary, not base64. Every
|
|
194
|
+
* outbound byte funnels through here, so it's also where `mudix.debugTelnet`
|
|
195
|
+
* mirrors what we send. */
|
|
196
|
+
private sendBytes;
|
|
197
|
+
sendGmcp(path: string, payload?: unknown): void;
|
|
198
|
+
/** Announce ourselves to the server right after GMCP is negotiated, the way
|
|
199
|
+
* Mudlet does: `Core.Hello` identifies the client (name + version) and
|
|
200
|
+
* `Core.Supports.Set` lists the GMCP modules we understand. Many servers
|
|
201
|
+
* won't push any GMCP data (room, char, vitals, …) until they've received
|
|
202
|
+
* this hello, so without it GMCP effectively does nothing. Latched so a
|
|
203
|
+
* repeated WILL/DO GMCP doesn't re-announce. Reports our own identity
|
|
204
|
+
* (see src/version.ts), matching the TTYPE/MNES/MXP handshakes. */
|
|
205
|
+
private sendGmcpHandshake;
|
|
206
|
+
/** Route GMCP `Char.Login.*` messages. The server sends `Char.Login.Default
|
|
207
|
+
* { "type": [...] }` to request login and then *waits* for the client to
|
|
208
|
+
* supply credentials — withholding the normal text "By what name…" prompt
|
|
209
|
+
* until it hears back (servers that do this gate on the `Char.Login` module
|
|
210
|
+
* we advertise in `Core.Supports.Set`). We surface it as `charLogin.request`
|
|
211
|
+
* so the UI can pop a credentials form; the UI replies via
|
|
212
|
+
* `sendCharLoginCredentials`, or an empty reply (cancel) to fall back to the
|
|
213
|
+
* text login (the behaviour Mudlet/Mudlet#7377 is about). `Char.Login.Result`
|
|
214
|
+
* carries the outcome. Path match is case-insensitive — GMCP module casing
|
|
215
|
+
* varies between servers. */
|
|
216
|
+
private handleCharLogin;
|
|
217
|
+
/** Send the GMCP `Char.Login.Credentials` reply. With an account, sends
|
|
218
|
+
* `{ account, password }` (account may be `"account:character"` for games
|
|
219
|
+
* with both); with no account it sends the empty `{}` form — the spec's
|
|
220
|
+
* "no credentials, fall back to your next auth method" signal, used when the
|
|
221
|
+
* user cancels the popup. mudix never stores the password; it only relays it. */
|
|
222
|
+
sendCharLoginCredentials(account?: string, password?: string): void;
|
|
223
|
+
sendGmcpRaw(message: string): void;
|
|
224
|
+
/** Mudlet `sendMSDP(variable, ...values)`. Frames + sends an MSDP
|
|
225
|
+
* subnegotiation. Returns false when the socket isn't open. */
|
|
226
|
+
sendMSDP(variable: string, values: string[]): boolean;
|
|
227
|
+
/** Mudlet `sendATCP(message)`. Frames `IAC SB ATCP <message> IAC SE` (ATCP =
|
|
228
|
+
* telnet option 200, GMCP's predecessor) and sends it raw. Returns false
|
|
229
|
+
* when the socket isn't open. */
|
|
230
|
+
sendATCP(message: string): boolean;
|
|
231
|
+
/** Mudlet `sendTelnetChannel102(msg)`. Frames `IAC SB 102 <msg> IAC SE`
|
|
232
|
+
* (the zMUD generic out-of-band channel) and sends it raw. Returns false
|
|
233
|
+
* when the socket isn't open. */
|
|
234
|
+
sendTelnetChannel102(msg: string): boolean;
|
|
235
|
+
/** Frame a raw `IAC SB <opt> <payload> IAC SE` subnegotiation and send it
|
|
236
|
+
* with no encoding conversion (each char → one byte), like the other
|
|
237
|
+
* telnet negotiations. Shared by sendATCP / sendTelnetChannel102. */
|
|
238
|
+
private sendSubnegotiation;
|
|
239
|
+
/** Mudlet `getServerEncoding()`. The IANA name of the decoder currently
|
|
240
|
+
* applied to the inbound stream — 'utf-8' until CHARSET negotiation (or an
|
|
241
|
+
* explicit setServerEncoding) swaps it. */
|
|
242
|
+
getServerEncoding(): string;
|
|
243
|
+
/** Mudlet `setServerEncoding(name)`. Switch the inbound decoder to `name`
|
|
244
|
+
* (any value from getServerEncodingsList()). Returns false — leaving the
|
|
245
|
+
* current encoding untouched — when the name isn't one we can decode. */
|
|
246
|
+
setServerEncoding(name: string): boolean;
|
|
247
|
+
/** Route an `IAC SB MSP ... IAC SE` body to the MSP parser and dispatch
|
|
248
|
+
* any parsed commands as `msp` events. Always runs when an MSP subneg
|
|
249
|
+
* arrives — once the server has bothered to wrap a tag, we trust it. */
|
|
250
|
+
private handleMspSubneg;
|
|
251
|
+
/** Report the main output window's character grid (columns × rows) for NAWS.
|
|
252
|
+
* The session calls this on every output-area resize. See TelnetNegotiator. */
|
|
253
|
+
setWindowSize(cols: number, rows: number): void;
|
|
254
|
+
/** Mudlet `sendSocket(data)`. Sends literal bytes over the socket with no
|
|
255
|
+
* telnet/encoding processing (each char becomes one byte). Returns false
|
|
256
|
+
* when the socket isn't open. */
|
|
257
|
+
sendSocket(data: string): boolean;
|
|
258
|
+
/** Mudlet `feedTelnet(data)`. Injects raw bytes into the inbound pipeline
|
|
259
|
+
* as if they had arrived from the server — they pass through telnet
|
|
260
|
+
* stripping, ANSI parsing, the trigger pipeline, and rendering. `data` is
|
|
261
|
+
* treated as a Latin-1 byte-string (matching incoming-frame handling). */
|
|
262
|
+
feedTelnet(data: string): void;
|
|
263
|
+
output(text?: string | AnsiAwareBuffer, type?: string, timestamp?: number): void;
|
|
264
|
+
/** Push a line directly into the message buffer for trigger processing + rendering via flushLines. */
|
|
265
|
+
pushLine(text: string, type: string): void;
|
|
266
|
+
private processIncomingData;
|
|
267
|
+
flushMessageBuffer(): void;
|
|
268
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export interface PingEventSource {
|
|
2
|
+
on(event: 'gmcp.negotiated', handler: () => void): () => void;
|
|
3
|
+
on(event: 'client.disconnect', handler: () => void): () => void;
|
|
4
|
+
on(event: 'gmcp.core.ping', handler: () => void): () => void;
|
|
5
|
+
}
|
|
6
|
+
export declare class PingTracker {
|
|
7
|
+
private readonly sendPingCommand;
|
|
8
|
+
private readonly onPing;
|
|
9
|
+
private timer;
|
|
10
|
+
private probeTimer;
|
|
11
|
+
private lastSentAt;
|
|
12
|
+
private lastDuration;
|
|
13
|
+
private supported;
|
|
14
|
+
private readonly unsubs;
|
|
15
|
+
constructor(sendPingCommand: (latencyMs: number) => void, onPing: (duration: number | null) => void, source: PingEventSource);
|
|
16
|
+
destroy(): void;
|
|
17
|
+
private probe;
|
|
18
|
+
private start;
|
|
19
|
+
private stop;
|
|
20
|
+
/** Sends the last round-trip we measured, per the GMCP spec's documented
|
|
21
|
+
* `Core.Ping <average latency>` form — 0 on the first probe, when there is
|
|
22
|
+
* nothing measured yet. The latency is informational to the server; what
|
|
23
|
+
* matters here is that the request always carries a body, since a bare
|
|
24
|
+
* `Core.Ping` makes servers that unconditionally JSON-parse the part after
|
|
25
|
+
* the module name choke on an empty string. */
|
|
26
|
+
private sendPing;
|
|
27
|
+
private handlePingResponse;
|
|
28
|
+
}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import type { EventBus } from "../../core/EventBus";
|
|
2
|
+
import type { MudClientEvents } from "../events";
|
|
3
|
+
export interface TelnetNegotiatorFlags {
|
|
4
|
+
gmcpEnabled: boolean;
|
|
5
|
+
mttsEnabled: boolean;
|
|
6
|
+
msdpEnabled: boolean;
|
|
7
|
+
msspEnabled: boolean;
|
|
8
|
+
charsetEnabled: boolean;
|
|
9
|
+
mspEnabled: boolean;
|
|
10
|
+
mxpEnabled: boolean;
|
|
11
|
+
mnesEnabled: boolean;
|
|
12
|
+
newEnvironEnabled: boolean;
|
|
13
|
+
nawsEnabled: boolean;
|
|
14
|
+
/** Whether the game-facing transport is TLS (MTTS SSL bit, NEW-ENVIRON TLS var). */
|
|
15
|
+
secureTransport: boolean;
|
|
16
|
+
/** Whether to advertise screen-reader use (MTTS SCREEN READER bit,
|
|
17
|
+
* NEW-ENVIRON SCREEN_READER var) — Mudlet's `advertiseScreenReader` config
|
|
18
|
+
* key. Default false; some MUDs adjust their output (e.g. suppress ASCII
|
|
19
|
+
* art, add extra room-description detail) when this is set. */
|
|
20
|
+
screenReaderAdvertised: boolean;
|
|
21
|
+
}
|
|
22
|
+
export interface TelnetNegotiatorHooks {
|
|
23
|
+
sendRaw(data: string): void;
|
|
24
|
+
/** GMCP came up — send the Core.Hello / Core.Supports.Set handshake
|
|
25
|
+
* (latched by the owner so a re-offer doesn't re-announce). */
|
|
26
|
+
onGmcpNegotiated(): void;
|
|
27
|
+
/** CHARSET came up — kick off the client-driven REQUEST listing our
|
|
28
|
+
* preferred encodings. */
|
|
29
|
+
onCharsetNegotiated(): void;
|
|
30
|
+
/** Current inbound encoding (IANA label) — drives the MTTS UTF-8 bit and
|
|
31
|
+
* the MNES/NEW-ENVIRON CHARSET variable. */
|
|
32
|
+
getEncoding(): string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Telnet option negotiation for a MUD session. Owns the WILL/WONT/DO/DONT
|
|
36
|
+
* response policy, the per-session negotiation latches (TTYPE cycle position,
|
|
37
|
+
* MXP started, NAWS accepted), the Mudlet `addSupportedTelnetOption` registry,
|
|
38
|
+
* and the `telnet.event` (sysTelnetEvent) surface for everything unrecognized.
|
|
39
|
+
*
|
|
40
|
+
* `processFrame` makes a single position-aware walk over each incoming frame's
|
|
41
|
+
* IAC sequences — skipping subnegotiation payloads and escaped `IAC IAC` bytes
|
|
42
|
+
* so data bytes can't be mistaken for negotiation commands — and buffers a
|
|
43
|
+
* trailing incomplete sequence for the next frame. Subnegotiation *bodies*
|
|
44
|
+
* (SB … SE payloads) are not parsed here; they arrive via the handleXxxSubneg
|
|
45
|
+
* methods, routed by MudClient's option parser.
|
|
46
|
+
*/
|
|
47
|
+
export declare class TelnetNegotiator {
|
|
48
|
+
private readonly flags;
|
|
49
|
+
private readonly eventBus;
|
|
50
|
+
private readonly hooks;
|
|
51
|
+
/** Mudlet `addSupportedTelnetOption(option)` registry. On IAC WILL <opt>
|
|
52
|
+
* we reply IAC DO <opt>; on IAC DO <opt> we reply IAC WILL <opt>. Options
|
|
53
|
+
* negotiated natively (GMCP/MSDP/TTYPE/…) are excluded — they have their
|
|
54
|
+
* own response logic. Survives reconnects (matches the old client-field
|
|
55
|
+
* lifetime: the registry lives as long as the client instance). */
|
|
56
|
+
private readonly supportedTelnetOptions;
|
|
57
|
+
/** Per-incoming-frame dedupe. Keys below 0x100 mark a natively-handled
|
|
58
|
+
* option as already answered this frame (mirroring the old one-response-
|
|
59
|
+
* per-frame `includes()` behavior); keys `(cmd << 8) | opt` mark a
|
|
60
|
+
* `telnet.event` as already raised. Telnet sequences can repeat across
|
|
61
|
+
* frames, so we only suppress duplicates within a single frame to avoid
|
|
62
|
+
* event storms. */
|
|
63
|
+
private readonly frameSeen;
|
|
64
|
+
/** Trailing bytes of a frame that might be the start of a split IAC
|
|
65
|
+
* sequence (a bare IAC, IAC WILL with no option byte yet, or an IAC SB
|
|
66
|
+
* whose IAC SE hasn't arrived) — prepended to the next frame so
|
|
67
|
+
* negotiation commands split across WebSocket frames aren't missed. */
|
|
68
|
+
private carry;
|
|
69
|
+
/** MTTS cycle position. The server issues SB TTYPE SEND repeatedly; we walk
|
|
70
|
+
* through client name (0), terminal type (1), then the MTTS bitvector (2+).
|
|
71
|
+
* Reset on each connect(). */
|
|
72
|
+
private ttypeStep;
|
|
73
|
+
/** Latches true once MXP has started for this session — via telnet option 91
|
|
74
|
+
* negotiation OR by detecting an in-band MXP line-mode sequence (`ESC[<n>z`).
|
|
75
|
+
* Many MUDs enable MXP server-side and just start streaming tags without the
|
|
76
|
+
* telnet handshake, so the in-band signal is the reliable trigger. Reset on
|
|
77
|
+
* each connect(). */
|
|
78
|
+
private mxpStarted;
|
|
79
|
+
/** True once we've sent IAC WILL NAWS this session (proactively on connect,
|
|
80
|
+
* or in response to a server-initiated IAC DO NAWS), so we don't re-offer. */
|
|
81
|
+
private nawsWillSent;
|
|
82
|
+
/** True once the server has accepted NAWS (IAC DO NAWS). Gates whether a
|
|
83
|
+
* window-size change is pushed to the server. */
|
|
84
|
+
private nawsNegotiated;
|
|
85
|
+
/** True once MSP has actually been negotiated (either direction) this
|
|
86
|
+
* connection. Mirrors Mudlet's `ctelnet::enableMSP` — the profile config
|
|
87
|
+
* only decides whether we're willing to negotiate; this records that we
|
|
88
|
+
* did. See {@link isMspNegotiated}. */
|
|
89
|
+
private mspNegotiated;
|
|
90
|
+
/** Latest known main output window size in character columns × rows, fed in
|
|
91
|
+
* by the session's resize observer via setWindowSize(). Null until the UI
|
|
92
|
+
* has measured the grid at least once. Deliberately NOT cleared by reset()
|
|
93
|
+
* so a reconnect keeps reporting the current grid. */
|
|
94
|
+
private windowSize;
|
|
95
|
+
/** Latches true once the server has asked us to suppress go-ahead (IAC WILL
|
|
96
|
+
* SGA). mudix refuses SGA (line mode only), but records the request:
|
|
97
|
+
* combined with active server echo it's the character-at-a-time signature
|
|
98
|
+
* the owner uses to raise `sysCharacterModeDetected`. Reset on connect(). */
|
|
99
|
+
private serverRequestedSGA;
|
|
100
|
+
constructor(flags: TelnetNegotiatorFlags, eventBus: EventBus<MudClientEvents>, hooks: TelnetNegotiatorHooks);
|
|
101
|
+
/** Clear the per-connection latches (call on connect). */
|
|
102
|
+
reset(): void;
|
|
103
|
+
/** Whether MSP was actually negotiated with the server this connection —
|
|
104
|
+
* Mudlet's `ctelnet::enableMSP`, distinct from the profile's `enableMSP`
|
|
105
|
+
* config (which only decides whether we agree to negotiate at all). Gates
|
|
106
|
+
* `receiveMSP`, which Mudlet refuses unless the option is live. */
|
|
107
|
+
isMspNegotiated(): boolean;
|
|
108
|
+
/** Drop the negotiated-MSP latch without resetting the rest of the
|
|
109
|
+
* negotiation state — used on disconnect, where the option dies with the
|
|
110
|
+
* connection but reset() isn't otherwise run. */
|
|
111
|
+
clearMspNegotiated(): void;
|
|
112
|
+
/** Whether the server has asked us to suppress go-ahead this connection
|
|
113
|
+
* (IAC WILL SGA). We refuse SGA, but the owner combines this with the
|
|
114
|
+
* echo state to detect character-at-a-time mode. */
|
|
115
|
+
get sgaRequested(): boolean;
|
|
116
|
+
/** The WebSocket handshake completed — proactively offer NAWS (RFC 1073
|
|
117
|
+
* has the window-owning side send WILL). The server replies IAC DO NAWS —
|
|
118
|
+
* handled in processFrame — at which point we send the actual dimensions.
|
|
119
|
+
* Harmless if the server doesn't support it (it answers DONT or ignores us). */
|
|
120
|
+
onSocketOpen(): void;
|
|
121
|
+
/** Mudlet `addSupportedTelnetOption(option)`. Marks the telnet option byte
|
|
122
|
+
* (0..255) as one the client will accept: on the next IAC WILL <opt> we
|
|
123
|
+
* reply IAC DO <opt>; on IAC DO <opt> we reply IAC WILL <opt>. Natively
|
|
124
|
+
* negotiated options (GMCP=201, MSDP=69, TTYPE=24, …) don't need to be
|
|
125
|
+
* registered. Returns true if the option was newly added, false if it was
|
|
126
|
+
* already present. */
|
|
127
|
+
addSupportedTelnetOption(option: number): boolean;
|
|
128
|
+
/** Record the main output window's character grid (columns × rows) for NAWS.
|
|
129
|
+
* The value is stored regardless of negotiation state (so a client created
|
|
130
|
+
* on a later connect can be seeded with the current size); it's only sent
|
|
131
|
+
* to the server once NAWS has been negotiated, and only when it changed. */
|
|
132
|
+
setWindowSize(cols: number, rows: number): void;
|
|
133
|
+
/** Walk one incoming frame (post-MCCP Latin-1 byte-string) for telnet IAC
|
|
134
|
+
* sequences: answer WILL/WONT/DO/DONT per the option policy, auto-respond
|
|
135
|
+
* to registered supported options, raise `telnet.event` for everything
|
|
136
|
+
* else (including SB of unrecognized options), and watch for in-band MXP
|
|
137
|
+
* line-mode sequences on servers that skip the option-91 handshake. */
|
|
138
|
+
processFrame(data: string): void;
|
|
139
|
+
/** One WILL/WONT/DO/DONT for `opt`. Natively-handled options are answered
|
|
140
|
+
* at most once per frame (matching the old `includes()`-based scan); the
|
|
141
|
+
* supported-options registry answers every occurrence; anything left is
|
|
142
|
+
* surfaced as a `telnet.event`. */
|
|
143
|
+
private handleNegotiationCommand;
|
|
144
|
+
private respondToKnownOption;
|
|
145
|
+
/** Raise `telnet.event` for an SB of an option we neither handle natively
|
|
146
|
+
* nor auto-negotiate (type 5 in Mudlet's sysTelnetEvent mapping). */
|
|
147
|
+
private noticeSubnegotiation;
|
|
148
|
+
/** `type` mirrors Mudlet's TLuaInterpreter mapping: 1=WILL, 2=WONT, 3=DO,
|
|
149
|
+
* 4=DONT, 5=SB. Deduped per (command, option) within the frame so a server
|
|
150
|
+
* that spams the same option doesn't flood handlers. */
|
|
151
|
+
private emitTelnetEvent;
|
|
152
|
+
/** Reply to a TERMINAL-TYPE / MTTS subnegotiation. `subneg` is the SB body
|
|
153
|
+
* with the option byte (24) at [0]; [1] is the request kind (1 = SEND). We
|
|
154
|
+
* answer `IAC SB TTYPE IS <value> IAC SE`, cycling client name → terminal
|
|
155
|
+
* type → MTTS capability bitvector on successive SENDs, then repeating the
|
|
156
|
+
* last value to signal the list is exhausted (RFC 1091 + the MTTS standard). */
|
|
157
|
+
handleTtypeSubneg(subneg: string): void;
|
|
158
|
+
/** Handle an `IAC SB MXP IAC SE` subnegotiation. Per spec it carries no
|
|
159
|
+
* payload — it merely confirms MXP is active — so we just start MXP. The
|
|
160
|
+
* actual MXP markup arrives in-band and is parsed downstream by the
|
|
161
|
+
* scripting engine. */
|
|
162
|
+
handleMxpSubneg(): void;
|
|
163
|
+
/** Answer an `IAC SB NEW-ENVIRON SEND … IAC SE` request, framed as
|
|
164
|
+
* `IAC SB NEW-ENVIRON IS <marker> … VALUE … IAC SE`. Telnet option 39 is
|
|
165
|
+
* shared by two modes: MNES reports the five core variables framed as VAR;
|
|
166
|
+
* plain NEW-ENVIRON reports the core set plus an extended capability set,
|
|
167
|
+
* framed as USERVAR. MNES takes precedence when both toggles are on
|
|
168
|
+
* (matching Mudlet). The server may request specific variables or send a
|
|
169
|
+
* bare SEND for all; selectMnesVars handles both. No-op when the option is
|
|
170
|
+
* off for this profile or on a malformed/non-SEND body. */
|
|
171
|
+
handleNewEnvironSubneg(subneg: string): void;
|
|
172
|
+
/** Build the option-39 variable set from live client state. CHARSET tracks
|
|
173
|
+
* the negotiated encoding; the extended NEW-ENVIRON capabilities derive from
|
|
174
|
+
* the game-facing transport (TLS — false in proxy mode) and the measured
|
|
175
|
+
* output grid (WORD_WRAP). The static identity (CLIENT_NAME/VERSION, MTTS,
|
|
176
|
+
* TERMINAL_TYPE) and the capability defaults live in buildNewEnvironVars. */
|
|
177
|
+
private collectNewEnvironVars;
|
|
178
|
+
/** Latch MXP on for this session and notify listeners. Idempotent — only the
|
|
179
|
+
* first call emits `mxp.negotiated`; later calls (repeat WILL/DO, in-band
|
|
180
|
+
* detection on subsequent frames) are no-ops. `viaTelnet` distinguishes a
|
|
181
|
+
* real option-91 handshake from in-band-only detection (see the event doc). */
|
|
182
|
+
private startMxp;
|
|
183
|
+
/** Send the current window size as an `IAC SB NAWS … IAC SE` subnegotiation.
|
|
184
|
+
* Falls back to a conventional 80×24 terminal default when the UI hasn't
|
|
185
|
+
* reported a real size yet — better than the NAWS 0×0 "no preference"
|
|
186
|
+
* sentinel, which some servers treat as "disable wrapping". */
|
|
187
|
+
private sendNawsSize;
|
|
188
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* localStorage-gated diagnostic logging for the MUD connection. Each gate is
|
|
3
|
+
* toggled from the browser console (e.g. `localStorage.setItem('mudix.debugTelnet',
|
|
4
|
+
* '1')`) and read live on every use, so logging can be flipped mid-session
|
|
5
|
+
* without a reconnect.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* `mudix.debugTelnet` — log every telnet command/subnegotiation byte seen on
|
|
9
|
+
* each incoming frame, and every byte-string we send. Used to investigate
|
|
10
|
+
* protocol-negotiation issues (GMCP/MSDP/MCCP not enabling) by revealing
|
|
11
|
+
* exactly what crosses the wire in both directions.
|
|
12
|
+
*/
|
|
13
|
+
export declare function debugTelnetEnabled(): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* `mudix.debugFrames` — log WebSocket frame boundaries for the MUD stream.
|
|
16
|
+
* Used to investigate "extra line break" issues that surface when long MUD
|
|
17
|
+
* lines arrive split across multiple WebSocket frames.
|
|
18
|
+
*/
|
|
19
|
+
export declare function debugFramesEnabled(): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* `mudix.debugMsp` — log MSP negotiation, parsed `!!SOUND`/`!!MUSIC` tags
|
|
22
|
+
* (inline and subneg), and their dispatch into the SoundManager. Use this to
|
|
23
|
+
* confirm whether a MUD is actually emitting MSP and whether the client is
|
|
24
|
+
* routing it through.
|
|
25
|
+
*/
|
|
26
|
+
export declare function debugMspEnabled(): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* `mudix.debugGmcp` — log every parsed GMCP message's path and (truncated) body
|
|
29
|
+
* as it arrives. Used to see exactly which modules a server drives — e.g.
|
|
30
|
+
* whether login audio comes over `Client.Media.*` GMCP vs. MSP tags.
|
|
31
|
+
*/
|
|
32
|
+
export declare function debugGmcpEnabled(): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* `mudix.debugGa` — log every IAC GA / IAC EOR prompt marker the server sends,
|
|
35
|
+
* plus the one-time moment the client latches into GA-driven prompt mode. Use
|
|
36
|
+
* this to confirm whether a MUD actually signals its prompts (GA-less MUDs rely
|
|
37
|
+
* on the `promptTimeoutMs` idle-flush fallback instead).
|
|
38
|
+
*/
|
|
39
|
+
export declare function debugGaEnabled(): boolean;
|
|
40
|
+
/** Scan a Latin-1 byte-string for telnet IAC sequences and log them in
|
|
41
|
+
* human-readable form. Logs SB option codes too (e.g. `SB GMCP` / `SB MSDP`). */
|
|
42
|
+
export declare function logTelnetNegotiation(label: string, s: string): void;
|
|
43
|
+
/**
|
|
44
|
+
* Log an outbound byte-string: the IAC sequences it carries plus the verbatim
|
|
45
|
+
* body of every subnegotiation, so a handshake payload a server rejects (a GMCP
|
|
46
|
+
* body it refuses to parse, say) is visible exactly as we framed it — the
|
|
47
|
+
* inbound `logTelnetNegotiation` only names options, which isn't enough to tell
|
|
48
|
+
* a malformed body from a well-formed one.
|
|
49
|
+
*
|
|
50
|
+
* Bodies only: plain command text is reported as a byte count, never content,
|
|
51
|
+
* because `send()` also carries typed passwords. `Char.Login.Credentials` is
|
|
52
|
+
* redacted for the same reason.
|
|
53
|
+
*/
|
|
54
|
+
export declare function logOutboundBytes(s: string): void;
|