@mudlet/mudlet-web 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +338 -338
- package/README.md +158 -150
- package/dist-lib/assets/qt-resources/index.d.ts +16 -0
- package/dist-lib/branding.d.ts +1 -1
- package/dist-lib/hooks/useMudSession.d.ts +1 -1
- package/dist-lib/hooks/useOutput.d.ts +3 -1
- package/dist-lib/import/defaultPackages.d.ts +35 -2
- package/dist-lib/import/defaults/generic_mapper/generic_mapper.mpackage +0 -0
- package/dist-lib/import/defaults/gui-drop/gui-drop.mpackage +0 -0
- package/dist-lib/import/defaults/{run-lua-code.mpackage → mudlet-base-ui/mudlet-base-ui.mpackage} +0 -0
- package/dist-lib/import/defaults/mudlet-mapper.xml +13023 -13023
- package/dist-lib/import/defaults/run-lua-code/run-lua-code.mpackage +0 -0
- package/dist-lib/import/packageExport.d.ts +71 -0
- package/dist-lib/import/packageInstaller.d.ts +4 -1
- package/dist-lib/index.js +45910 -39931
- package/dist-lib/logging/SessionLogger.d.ts +66 -1
- package/dist-lib/map/MapStore.d.ts +32 -4
- package/dist-lib/map/mapImageExport.d.ts +1 -1
- package/dist-lib/map/mapZoom.d.ts +71 -0
- package/dist-lib/mud/ItemIdSequence.d.ts +23 -0
- package/dist-lib/mud/MudSession.d.ts +113 -11
- package/dist-lib/mud/PatternEngine.d.ts +6 -1
- package/dist-lib/mud/commandSplit.d.ts +16 -0
- package/dist-lib/mud/connection/LineAssembler.d.ts +56 -0
- package/dist-lib/mud/connection/MudClient.d.ts +136 -19
- package/dist-lib/mud/connection/TelnetNegotiator.d.ts +39 -0
- package/dist-lib/mud/connection/telnetByteTags.d.ts +35 -0
- package/dist-lib/mud/events.d.ts +86 -4
- package/dist-lib/mud/games/bundledGames.d.ts +29 -0
- package/dist-lib/mud/games/gameIcons.d.ts +5 -0
- package/dist-lib/mud/keybindings/KeyEngine.d.ts +9 -2
- package/dist-lib/mud/keybindings/browserReservedKeys.d.ts +5 -1
- package/dist-lib/mud/keybindings/keyEventTarget.d.ts +17 -0
- package/dist-lib/mud/keybindings/qtKeys.d.ts +2 -0
- package/dist-lib/mud/protocol/charLoginFlow.d.ts +68 -0
- package/dist-lib/mud/protocol/charset.d.ts +27 -5
- package/dist-lib/mud/protocol/constants.d.ts +1 -0
- package/dist-lib/mud/protocol/gmcp.d.ts +19 -3
- package/dist-lib/mud/protocol/index.d.ts +1 -1
- package/dist-lib/mud/protocol/msspTls.d.ts +54 -0
- package/dist-lib/mud/protocol/mxp.d.ts +28 -5
- package/dist-lib/mud/protocol/tlsCodes.d.ts +4 -0
- package/dist-lib/mud/replay/ReplayPlayer.d.ts +17 -0
- package/dist-lib/mud/text/Console.d.ts +64 -0
- package/dist-lib/mud/text/FormatState.d.ts +66 -3
- package/dist-lib/mud/text/hyperlinkVisibility.d.ts +35 -0
- package/dist-lib/mud/text/osc8Docs.d.ts +23 -0
- package/dist-lib/mud/text/serverWrap.d.ts +191 -0
- package/dist-lib/mud/timers/TimerEngine.d.ts +43 -12
- package/dist-lib/mud/triggers/TriggerEngine.d.ts +112 -3
- package/dist-lib/scripting/EngineHost.d.ts +56 -3
- package/dist-lib/scripting/IScriptingRuntime.d.ts +22 -0
- package/dist-lib/scripting/MxpFrameManager.d.ts +118 -0
- package/dist-lib/scripting/ScriptingAPI.d.ts +331 -54
- package/dist-lib/scripting/ScriptingEngine.d.ts +181 -24
- package/dist-lib/scripting/http/HttpService.d.ts +51 -1
- package/dist-lib/scripting/lua/LuaRuntime.d.ts +159 -2
- package/dist-lib/scripting/lua/bindings/map.d.ts +0 -12
- package/dist-lib/scripting/lua/utf8Patterns.d.ts +59 -0
- package/dist-lib/storage/index.d.ts +1 -1
- package/dist-lib/storage/persistentStorage.d.ts +10 -0
- package/dist-lib/storage/schema.d.ts +166 -4
- package/dist-lib/styles.css +1 -1
- package/dist-lib/ui/BundledGameGrid.d.ts +21 -0
- package/dist-lib/ui/CharLoginModal.d.ts +5 -1
- package/dist-lib/ui/CommandBar.d.ts +7 -1
- package/dist-lib/ui/ConnectionGrid.d.ts +4 -1
- package/dist-lib/ui/FileBrowserModal.d.ts +1 -0
- package/dist-lib/ui/FilePickerModal.d.ts +3 -3
- package/dist-lib/ui/HelpModal.d.ts +11 -0
- package/dist-lib/ui/LogBrowserModal.d.ts +4 -1
- package/dist-lib/ui/PlayerMarkerPreview.d.ts +20 -0
- package/dist-lib/ui/SettingsModal.d.ts +5 -1
- package/dist-lib/ui/TlsAlertBanner.d.ts +18 -0
- package/dist-lib/ui/TlsCertificateBox.d.ts +20 -0
- package/dist-lib/ui/TlsUpgradeModal.d.ts +16 -0
- package/dist-lib/ui/Toolbar.d.ts +2 -1
- package/dist-lib/ui/VfsPickerModal.d.ts +26 -0
- package/dist-lib/ui/components/FileSourceButton.d.ts +47 -0
- package/dist-lib/ui/components/index.d.ts +1 -0
- package/dist-lib/ui/components/useModalFocus.d.ts +6 -0
- package/dist-lib/ui/helpTopics.d.ts +19 -0
- package/dist-lib/ui/labels/LabelManager.d.ts +32 -0
- package/dist-lib/ui/labels/labelLinks.d.ts +52 -0
- package/dist-lib/ui/layout/ScriptWindow.d.ts +11 -2
- package/dist-lib/ui/markdown.d.ts +10 -1
- package/dist-lib/ui/output/OutputArea.d.ts +11 -1
- package/dist-lib/ui/output/OutputContextMenu.d.ts +3 -1
- package/dist-lib/ui/output/OutputRenderer.d.ts +7 -1
- package/dist-lib/ui/output/OutputSearchBar.d.ts +25 -0
- package/dist-lib/ui/output/StickyOutputPanel.d.ts +5 -1
- package/dist-lib/ui/output/linkNavigation.d.ts +22 -0
- package/dist-lib/ui/output/outputSearch.d.ts +130 -0
- package/dist-lib/ui/search/matcher.d.ts +15 -0
- package/dist-lib/ui/search/useDebounced.d.ts +3 -0
- package/dist-lib/ui/tts/TtsManager.d.ts +3 -0
- package/dist-lib/ui/useCommandHistory.d.ts +4 -2
- package/dist-lib/ui/useOpenProfiles.d.ts +26 -0
- package/dist-lib/ui/video/VideoManager.d.ts +17 -0
- package/dist-lib/ui/windows/WindowManager.d.ts +149 -2
- package/dist-lib/ui/windows/panels/MapPanel.d.ts +4 -1
- package/dist-lib/ui/windows/panels/PackageExportModal.d.ts +18 -0
- package/dist-lib/ui/windows/panels/TextPanel.d.ts +3 -1
- package/dist-lib/ui/windows/types.d.ts +35 -0
- package/dist-lib/utils/describeThrown.d.ts +22 -0
- package/dist-lib/utils/fontLoader.d.ts +5 -0
- package/dist-lib/vfs-sw.js +131 -131
- package/dist-lib/vite.js +22 -0
- package/package.json +97 -93
- package/dist-lib/scripting/lua/mudlet-lua/generic-mapper/generic_mapper.mpackage +0 -0
- package/dist-lib/ui/windows/panels/VfsModulePickerModal.d.ts +0 -8
package/README.md
CHANGED
|
@@ -1,150 +1,158 @@
|
|
|
1
|
-
<div align="center">
|
|
2
|
-
|
|
3
|
-
# 🗺️ Mudlet Web
|
|
4
|
-
|
|
5
|
-
### Mudlet in your browser — the full Mudlet Lua scripting stack, running entirely client-side.
|
|
6
|
-
|
|
7
|
-
[](https://react.dev)
|
|
8
|
-
[](https://www.typescriptlang.org)
|
|
9
|
-
[](https://vite.dev)
|
|
10
|
-
[-000080?logo=lua&logoColor=white)](https://www.lua.org)
|
|
11
|
-
|
|
12
|
-
*No installs. No native dependencies. Open a tab and play.*
|
|
13
|
-
|
|
14
|
-
</div>
|
|
15
|
-
|
|
16
|
-
---
|
|
17
|
-
|
|
18
|
-
## What is Mudlet Web?
|
|
19
|
-
|
|
20
|
-
**Mudlet Web** is a browser edition of [Mudlet](https://www.mudlet.org/), the [MUD](https://en.wikipedia.org/wiki/Multi-user_dungeon) (Multi-User Dungeon) client. It speaks the full telnet protocol stack that modern MUDs use, renders rich ANSI output, and runs **real Lua scripting** compiled to WebAssembly — with an API built for **drop-in compatibility** with Mudlet packages, maps, and profiles.
|
|
21
|
-
|
|
22
|
-
If you have Mudlet scripts, triggers, aliases, or maps, Mudlet Web aims to run them unchanged — anywhere you have a web browser. It is not a rewrite of desktop Mudlet and doesn't replace it: some things a native client can do simply aren't available inside a browser sandbox (see [Limitations](#️-limitations--known-constraints)).
|
|
23
|
-
|
|
24
|
-
## ✨ Features
|
|
25
|
-
|
|
26
|
-
### 🔌 Connectivity
|
|
27
|
-
- **Direct WebSocket** connections to MUDs that expose a `ws(s)://` endpoint.
|
|
28
|
-
- **Telnet via proxy** — connect to any classic `host:port` MUD through the bundled telnet→WebSocket proxy.
|
|
29
|
-
- Full protocol support: **GMCP**, **MSDP**, **MSSP**, **MCCP** (compression), **MSP** (sound), telnet **CHARSET**, **TTYPE/MTTS**, and GA/EOR prompt detection.
|
|
30
|
-
|
|
31
|
-
### 📜 Mudlet Lua scripting
|
|
32
|
-
- A complete **Lua 5.1** runtime (WASM) with Mudlet-native globals — `send`, `echo`/`cecho`/`decho`/`hecho`, `tempTimer`, `tempTrigger`, `tempAlias`, and [hundreds more](docs/MUDLET_API.md).
|
|
33
|
-
- **Triggers, aliases, timers, keybindings, and buttons** organized in Mudlet-style folder trees.
|
|
34
|
-
- **PCRE regex** powered by `pcre2-wasm` — the same engine flavour as desktop Mudlet.
|
|
35
|
-
- Bundled Mudlet standard library: Geyser GUI toolkit, the generic mapper, string/table utilities, and the `db:*` database API.
|
|
36
|
-
- A built-in **CodeMirror** script editor with autocompletion for the entire API surface.
|
|
37
|
-
|
|
38
|
-
### 🗺️ Maps & GUI
|
|
39
|
-
- Renders **Mudlet binary maps** with a built-in viewer and editor.
|
|
40
|
-
- **Geyser** mini-consoles, labels, gauges, and command lines as pixel-positioned overlays.
|
|
41
|
-
- A **custom dock/float window system** — split, tab, dock to any edge, or tear off into free-floating windows.
|
|
42
|
-
|
|
43
|
-
### 💾 Storage & persistence
|
|
44
|
-
- A **per-profile virtual filesystem** (ZenFS) backed by IndexedDB — or linked to a **real folder on your disk** via the File System Access API, with two-way sync.
|
|
45
|
-
- An in-browser **SQLite** database for the Mudlet `db:*` API.
|
|
46
|
-
- **Session logging** to IndexedDB, browsable and exportable.
|
|
47
|
-
- Install Mudlet **packages and modules** (`.mpackage` / `.zip` / XML) — including browsing the public Mudlet package repository.
|
|
48
|
-
|
|
49
|
-
### 🎨 Polish
|
|
50
|
-
- Multiple themes (dark, light, amber, sky), custom fonts, configurable colors and backgrounds.
|
|
51
|
-
- Text-to-speech, sound, and video playback wired to Mudlet's media APIs.
|
|
52
|
-
|
|
53
|
-
## 🚀 Getting Started
|
|
54
|
-
|
|
55
|
-
### Prerequisites
|
|
56
|
-
- [Node.js](https://nodejs.org/) 20+ and [yarn](https://yarnpkg.com/).
|
|
57
|
-
|
|
58
|
-
### Run the client
|
|
59
|
-
|
|
60
|
-
```bash
|
|
61
|
-
git clone <repo-url> mudlet-web
|
|
62
|
-
cd mudlet-web
|
|
63
|
-
yarn
|
|
64
|
-
yarn dev
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
Open the printed local URL (usually `http://localhost:5173`) in your browser, then create a connection on the start screen.
|
|
68
|
-
|
|
69
|
-
### Run the telnet proxy (for `host:port` MUDs)
|
|
70
|
-
|
|
71
|
-
The browser cannot open raw TCP sockets, so connecting to a classic telnet MUD needs the small bundled proxy:
|
|
72
|
-
|
|
73
|
-
```bash
|
|
74
|
-
cd proxy
|
|
75
|
-
yarn
|
|
76
|
-
yarn start # listens on ws://localhost:3001 by default
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
Then choose **MUD (host:port)** mode when creating a connection. Servers that expose a native WebSocket endpoint don't need the proxy — use **WebSocket** mode and point it straight at the `ws(s)://` URL.
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
##
|
|
123
|
-
|
|
124
|
-
Mudlet Web
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
- **
|
|
133
|
-
- **
|
|
134
|
-
- **
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# 🗺️ Mudlet Web
|
|
4
|
+
|
|
5
|
+
### Mudlet in your browser — the full Mudlet Lua scripting stack, running entirely client-side.
|
|
6
|
+
|
|
7
|
+
[](https://react.dev)
|
|
8
|
+
[](https://www.typescriptlang.org)
|
|
9
|
+
[](https://vite.dev)
|
|
10
|
+
[-000080?logo=lua&logoColor=white)](https://www.lua.org)
|
|
11
|
+
|
|
12
|
+
*No installs. No native dependencies. Open a tab and play.*
|
|
13
|
+
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## What is Mudlet Web?
|
|
19
|
+
|
|
20
|
+
**Mudlet Web** is a browser edition of [Mudlet](https://www.mudlet.org/), the [MUD](https://en.wikipedia.org/wiki/Multi-user_dungeon) (Multi-User Dungeon) client. It speaks the full telnet protocol stack that modern MUDs use, renders rich ANSI output, and runs **real Lua scripting** compiled to WebAssembly — with an API built for **drop-in compatibility** with Mudlet packages, maps, and profiles.
|
|
21
|
+
|
|
22
|
+
If you have Mudlet scripts, triggers, aliases, or maps, Mudlet Web aims to run them unchanged — anywhere you have a web browser. It is not a rewrite of desktop Mudlet and doesn't replace it: some things a native client can do simply aren't available inside a browser sandbox (see [Limitations](#️-limitations--known-constraints)).
|
|
23
|
+
|
|
24
|
+
## ✨ Features
|
|
25
|
+
|
|
26
|
+
### 🔌 Connectivity
|
|
27
|
+
- **Direct WebSocket** connections to MUDs that expose a `ws(s)://` endpoint.
|
|
28
|
+
- **Telnet via proxy** — connect to any classic `host:port` MUD through the bundled telnet→WebSocket proxy.
|
|
29
|
+
- Full protocol support: **GMCP**, **MSDP**, **MSSP**, **MCCP** (compression), **MSP** (sound), telnet **CHARSET**, **TTYPE/MTTS**, and GA/EOR prompt detection.
|
|
30
|
+
|
|
31
|
+
### 📜 Mudlet Lua scripting
|
|
32
|
+
- A complete **Lua 5.1** runtime (WASM) with Mudlet-native globals — `send`, `echo`/`cecho`/`decho`/`hecho`, `tempTimer`, `tempTrigger`, `tempAlias`, and [hundreds more](docs/MUDLET_API.md).
|
|
33
|
+
- **Triggers, aliases, timers, keybindings, and buttons** organized in Mudlet-style folder trees.
|
|
34
|
+
- **PCRE regex** powered by `pcre2-wasm` — the same engine flavour as desktop Mudlet.
|
|
35
|
+
- Bundled Mudlet standard library: Geyser GUI toolkit, the generic mapper, string/table utilities, and the `db:*` database API.
|
|
36
|
+
- A built-in **CodeMirror** script editor with autocompletion for the entire API surface.
|
|
37
|
+
|
|
38
|
+
### 🗺️ Maps & GUI
|
|
39
|
+
- Renders **Mudlet binary maps** with a built-in viewer and editor.
|
|
40
|
+
- **Geyser** mini-consoles, labels, gauges, and command lines as pixel-positioned overlays.
|
|
41
|
+
- A **custom dock/float window system** — split, tab, dock to any edge, or tear off into free-floating windows.
|
|
42
|
+
|
|
43
|
+
### 💾 Storage & persistence
|
|
44
|
+
- A **per-profile virtual filesystem** (ZenFS) backed by IndexedDB — or linked to a **real folder on your disk** via the File System Access API, with two-way sync.
|
|
45
|
+
- An in-browser **SQLite** database for the Mudlet `db:*` API.
|
|
46
|
+
- **Session logging** to IndexedDB, browsable and exportable.
|
|
47
|
+
- Install Mudlet **packages and modules** (`.mpackage` / `.zip` / XML) — including browsing the public Mudlet package repository.
|
|
48
|
+
|
|
49
|
+
### 🎨 Polish
|
|
50
|
+
- Multiple themes (dark, light, amber, sky), custom fonts, configurable colors and backgrounds.
|
|
51
|
+
- Text-to-speech, sound, and video playback wired to Mudlet's media APIs.
|
|
52
|
+
|
|
53
|
+
## 🚀 Getting Started
|
|
54
|
+
|
|
55
|
+
### Prerequisites
|
|
56
|
+
- [Node.js](https://nodejs.org/) 20+ and [yarn](https://yarnpkg.com/).
|
|
57
|
+
|
|
58
|
+
### Run the client
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
git clone <repo-url> mudlet-web
|
|
62
|
+
cd mudlet-web
|
|
63
|
+
yarn
|
|
64
|
+
yarn dev
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Open the printed local URL (usually `http://localhost:5173`) in your browser, then create a connection on the start screen.
|
|
68
|
+
|
|
69
|
+
### Run the telnet proxy (for `host:port` MUDs)
|
|
70
|
+
|
|
71
|
+
The browser cannot open raw TCP sockets, so connecting to a classic telnet MUD needs the small bundled proxy:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
cd proxy
|
|
75
|
+
yarn
|
|
76
|
+
yarn start # listens on ws://localhost:3001 by default
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Then choose **MUD (host:port)** mode when creating a connection. Servers that expose a native WebSocket endpoint don't need the proxy — use **WebSocket** mode and point it straight at the `ws(s)://` URL.
|
|
80
|
+
|
|
81
|
+
### Already play in desktop Mudlet?
|
|
82
|
+
|
|
83
|
+
Your existing profile comes across whole — triggers, aliases, scripts, keybindings, buttons, saved variables, installed packages, your map, and your colours and fonts. **[docs/help/migrating.md](docs/help/migrating.md)** walks through it: where the profile folder lives on each platform, the three ways in (copy a folder, import a `.zip`, or link the folder and keep using both), what doesn't come across, and how to export back to desktop Mudlet.
|
|
84
|
+
|
|
85
|
+
The same guide — plus [connecting](docs/help/connecting.md), [storage and backups](docs/help/storage.md), and [browsers and limits](docs/help/browsers.md) — is built into the app behind the **Help** button, on the start screen and in the toolbar.
|
|
86
|
+
|
|
87
|
+
## 🛠️ Development
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
yarn dev # Start the Vite dev server
|
|
91
|
+
yarn build # Type-check + production build
|
|
92
|
+
yarn preview # Preview the production build
|
|
93
|
+
yarn typecheck # Type-check only (src + tests)
|
|
94
|
+
yarn test # Run the Vitest suite
|
|
95
|
+
yarn test:watch # Vitest in watch mode
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Production builds deploy to **GitHub Pages** automatically on push to `master`.
|
|
99
|
+
|
|
100
|
+
## 🧱 Architecture at a glance
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
MudClient (WebSocket — direct or via telnet proxy)
|
|
104
|
+
→ telnet/protocol parsing (GMCP · MSDP · MSSP · MCCP · MSP · CHARSET · TTYPE)
|
|
105
|
+
→ MudSession.events (a typed EventBus — the spine of the app)
|
|
106
|
+
├─ ScriptingEngine → LuaRuntime (WASM) + alias/trigger/timer/key engines
|
|
107
|
+
├─ React UI (output area, dock/float panels, toolbar)
|
|
108
|
+
└─ SessionLogger (persists output to IndexedDB)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
| Layer | Lives in | Notes |
|
|
112
|
+
|---|---|---|
|
|
113
|
+
| **Connection** | `src/mud/connection`, `src/mud/protocol` | Telnet over binary WebSocket frames |
|
|
114
|
+
| **Scripting** | `src/scripting` | wasmoon Lua 5.1, Mudlet-native API, bundled Mudlet Lua |
|
|
115
|
+
| **UI / Windows** | `src/ui` | Custom dock/float layout, CodeMirror editor, overlays |
|
|
116
|
+
| **Maps** | `src/map`, `MapPanel` | Mudlet binary map reader/renderer/editor |
|
|
117
|
+
| **Storage** | `src/storage`, `src/scripting/vfs`, `src/db` | Zustand + per-profile VFS + SQLite + IndexedDB logs |
|
|
118
|
+
| **Import** | `src/import` | Mudlet XML & package install/export |
|
|
119
|
+
|
|
120
|
+
A deeper tour of the internals lives in [`CLAUDE.md`](./CLAUDE.md); the full Mudlet API implementation status is tracked in [`MUDLET_API.md`](docs/MUDLET_API.md).
|
|
121
|
+
|
|
122
|
+
## 🏷️ Branded builds
|
|
123
|
+
|
|
124
|
+
Mudlet Web is also published as an npm library for shipping a **white-label client for one specific MUD** — your own name, login screen, theme, toolbar, and bundled Lua packages, without forking the repo. See [`docs/BRANDED_BUILDS.md`](docs/BRANDED_BUILDS.md) for the setup guide, or [embervale-web](https://github.com/Delwing/embervale-web) for a live example.
|
|
125
|
+
|
|
126
|
+
> The package is published as [`@mudlet/mudlet-web`](https://www.npmjs.com/package/@mudlet/mudlet-web). It was previously `@delwing/mudix` (now deprecated) — the app root export was renamed `MudixApp` → `MudletWebApp` with the move.
|
|
127
|
+
|
|
128
|
+
## ⚠️ Limitations & known constraints
|
|
129
|
+
|
|
130
|
+
Mudlet Web runs inside a browser sandbox, which trades some of desktop Mudlet's native reach for zero-install portability. Worth knowing before you switch:
|
|
131
|
+
|
|
132
|
+
- **Telnet MUDs need the proxy.** Browsers can't open raw TCP sockets, so classic `host:port` MUDs are reachable only through the bundled telnet→WebSocket proxy. Servers with a native `ws(s)://` endpoint connect directly.
|
|
133
|
+
- **One profile per tab.** There's no desktop-Mudlet-style multi-profile tabbing *within* a tab — you open one connection per browser tab (`loadProfile()` and in-tab profile switching are no-op stubs). You can still run **different profiles in separate tabs**: each profile is locked to a single tab (opening the same one elsewhere shows a "waiting" screen until the first tab releases it), every profile's data is isolated in its own filesystem, and profiles can signal each other across tabs via Mudlet's `raiseGlobalEvent`.
|
|
134
|
+
- **Storage is browser-scoped.** Profiles, scripts, maps, and logs live in the browser's IndexedDB/localStorage for the app's origin. Clearing site data wipes them — unless you **link a real disk folder** for that profile (see below). Different browsers/machines don't share state automatically.
|
|
135
|
+
- **Disk-folder linking is Chromium-only.** The "link a folder on disk" feature uses the File System Access API, which Firefox and Safari don't implement. Those browsers fall back to IndexedDB-only storage.
|
|
136
|
+
- **Secure context required.** The VFS service worker (which serves profile images/fonts/CSS) needs HTTPS or `localhost`.
|
|
137
|
+
- **Clipboard access is best-effort.** The browser's OS clipboard is asynchronous and gated on a user gesture (and a secure context), whereas desktop Mudlet's `getClipboardText`/`setClipboardText` are synchronous. Mudlet Web keeps a session-local text-clipboard mirror as the authoritative value and syncs it to the real OS clipboard opportunistically — so `setClipboardText` may not reach the system clipboard without a user gesture, and `getClipboardText` returns the last value Mudlet Web knows about (an external copy made elsewhere shows up on the *next* call, once the async read completes). This mirror is separate from the rich-text buffer used by `copy()`/`paste()`.
|
|
138
|
+
- **Some Mudlet APIs are stubbed or partial.** Anything fundamentally native is bound as a warning-emitting no-op so imported packages still load, but does nothing: **Discord** Rich Presence, **IRC** client, OS `spawn`/subprocess, and the system dictionary. A few synchronous Mudlet calls (`invokeFileDialog`, `getImageSize`) don't map cleanly onto the browser's async pickers/loaders and are still in progress. See [`MUDLET_API.md`](docs/MUDLET_API.md) for the per-function status (✅ / ⚠️ / 🚧 / ❌).
|
|
139
|
+
- **The main window is the viewport.** Calls like `setMainWindowSize` are no-ops — the browser window is the main window.
|
|
140
|
+
- **The Lua↔JS boundary has a per-call cost.** Each crossing between the Lua VM and JS is cheap individually but adds up — a script that makes thousands of tiny boundary calls in a tight loop (e.g. iterating every room in a large area one `getRoom*` call at a time) will feel noticeably slower than in native Mudlet. The hot paths you actually hit constantly (line/trigger processing, GMCP) are batched and stay fast; prefer bulk/batched APIs over per-item calls when you can.
|
|
141
|
+
|
|
142
|
+
## 🤝 Contributing
|
|
143
|
+
|
|
144
|
+
When adding a Mudlet API function, implement the JS-side method in `ScriptingAPI`, bind the Lua global in `LuaRuntime`, and add the autocomplete entry in `luaCompletions.ts`. Run `yarn typecheck` and `yarn test` before opening a PR.
|
|
145
|
+
|
|
146
|
+
## License
|
|
147
|
+
|
|
148
|
+
Mudlet Web is licensed under the **GNU General Public License, version 2 or (at your option) any later version** — see [LICENSE](./LICENSE). This matches [Mudlet](https://github.com/Mudlet/Mudlet)'s license (GPL-2.0-or-later): Mudlet Web bundles Mudlet's Lua runtime files (`src/scripting/lua/mudlet-lua/` — LuaGlobal, Geyser, the generic mapper, DB utilities, and more), copyright the Mudlet contributors, so every distribution is a combined work with that GPL code.
|
|
149
|
+
|
|
150
|
+
Lua scripts and packages that Mudlet Web merely *runs* (your profile scripts, installed `.mpackage`s, branded-build packages) are separate works and are not required to be GPL — the same way the Mudlet ecosystem treats its packages.
|
|
151
|
+
|
|
152
|
+
Mudlet Web also bundles **Bitstream Vera Sans Mono** (`src/assets/fonts/bitstream-vera-sans-mono/`) as the default console output and command-line font, matching Mudlet's own default console typeface. It's under the separate, permissive [Bitstream Vera license](src/assets/fonts/bitstream-vera-sans-mono/COPYRIGHT.TXT) (free redistribution and embedding; just don't sell the font standalone or rename a modified copy while keeping "Bitstream"/"Vera" in the name).
|
|
153
|
+
|
|
154
|
+
**Ubuntu** and **Ubuntu Mono** (`src/assets/fonts/ubuntu/`, regular/bold/italic/bold-italic each) are bundled for the same reason: Mudlet registers both families into Qt's font database at startup, so packages written for Mudlet — including the bundled `mudlet-base-ui` — ask for them by name for labels, headers, and miniconsole stylesheets. They're under the [Ubuntu Font Licence 1.0](src/assets/fonts/ubuntu/LICENCE.txt) (free redistribution and embedding; modified copies must be renamed).
|
|
155
|
+
|
|
156
|
+
<div align="center">
|
|
157
|
+
<sub>Built with React, TypeScript, and a lot of WebAssembly. Happy MUDding. 🐉</sub>
|
|
158
|
+
</div>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** Whether `path` uses Qt's resource syntax. Mudlet also accepts the `qrc:///`
|
|
2
|
+
* URL form for the same bundle. */
|
|
3
|
+
export declare function isQtResourcePath(path: string): boolean;
|
|
4
|
+
/**
|
|
5
|
+
* A `:/…` path as a URL usable anywhere a browser wants one — an `<img>` src, a
|
|
6
|
+
* CSS `url(...)`, a background image. Null when the resource isn't vendored.
|
|
7
|
+
*/
|
|
8
|
+
export declare function qtResourceUrl(path: string): string | null;
|
|
9
|
+
/**
|
|
10
|
+
* The bytes behind a `:/…` path, decoded synchronously. Null when the resource
|
|
11
|
+
* isn't vendored, or the entry isn't a base64 data URI (which would mean the
|
|
12
|
+
* bundler emitted it as a file instead of inlining it).
|
|
13
|
+
*/
|
|
14
|
+
export declare function qtResourceBytes(path: string): Uint8Array | null;
|
|
15
|
+
/** Every vendored resource path, in Qt form. For diagnostics and tests. */
|
|
16
|
+
export declare function qtResourcePaths(): string[];
|
package/dist-lib/branding.d.ts
CHANGED
|
@@ -70,7 +70,7 @@ export declare const STOCK_THEMES: {
|
|
|
70
70
|
/** Ids of the stock toolbar buttons, for `BrandToolbarConfig.hide`.
|
|
71
71
|
* `connection` is the Reconnect/Disconnect pair; `close` closes the profile;
|
|
72
72
|
* `record` toggles Mudlet-format replay recording. */
|
|
73
|
-
export type StockToolbarButton = 'scripts' | 'files' | 'map' | 'logs' | 'docs' | 'reportBug' | 'settings' | 'record' | 'connection' | 'close';
|
|
73
|
+
export type StockToolbarButton = 'scripts' | 'files' | 'map' | 'logs' | 'docs' | 'help' | 'reportBug' | 'settings' | 'record' | 'connection' | 'close';
|
|
74
74
|
/** What a brand toolbar button can do when clicked. */
|
|
75
75
|
export interface BrandToolbarContext {
|
|
76
76
|
connectionId: string;
|
|
@@ -6,5 +6,5 @@ export declare function useMudSession(options?: MudSessionOptions): {
|
|
|
6
6
|
passwordMode: boolean;
|
|
7
7
|
connect: (url: string) => void;
|
|
8
8
|
disconnect: () => void;
|
|
9
|
-
send: (text: string, echo?: boolean) => void;
|
|
9
|
+
send: (text: string, echo?: boolean, isGameCommand?: boolean) => void;
|
|
10
10
|
};
|
|
@@ -5,6 +5,8 @@ export interface UseStickyOutputOptions {
|
|
|
5
5
|
maxElements?: number;
|
|
6
6
|
splitViewThreshold?: number;
|
|
7
7
|
showTimestamps?: boolean;
|
|
8
|
+
/** See OutputHandlerOptions.followTail. Omit for a normal scrollback. */
|
|
9
|
+
followTail?: () => boolean;
|
|
8
10
|
}
|
|
9
11
|
export interface UseStickyOutputResult {
|
|
10
12
|
outputRef: React.RefObject<HTMLDivElement | null>;
|
|
@@ -14,4 +16,4 @@ export interface UseStickyOutputResult {
|
|
|
14
16
|
scrollToBottom: () => void;
|
|
15
17
|
controls: OutputRendererControls | null;
|
|
16
18
|
}
|
|
17
|
-
export declare function useStickyOutput(source: MessageSource | null, { stickyLines, maxElements, splitViewThreshold, showTimestamps, }?: UseStickyOutputOptions): UseStickyOutputResult;
|
|
19
|
+
export declare function useStickyOutput(source: MessageSource | null, { stickyLines, maxElements, splitViewThreshold, showTimestamps, followTail, }?: UseStickyOutputOptions): UseStickyOutputResult;
|
|
@@ -15,6 +15,13 @@ interface DefaultPackage {
|
|
|
15
15
|
* `mudlet-mapper.xml` row of `defaultScripts` in mudlet.cpp.
|
|
16
16
|
*/
|
|
17
17
|
export declare const IRE_MAPPER_GAMES: string[];
|
|
18
|
+
/**
|
|
19
|
+
* Games whose own bundled loader installs a full interface, so the starter UI is
|
|
20
|
+
* not preinstalled for them — it would only fight the game's GUI for the same
|
|
21
|
+
* screen space. Mirrors the `providesOwnUi` entries of `TGameDetails.h`'s
|
|
22
|
+
* `scmDefaultGames`, including each game's `alternateHostUrls`.
|
|
23
|
+
*/
|
|
24
|
+
export declare const GAMES_WITH_OWN_UI: string[];
|
|
18
25
|
/** Every bundled default, whatever the host — for tests and tooling. */
|
|
19
26
|
export declare const ALL_DEFAULTS: DefaultPackage[];
|
|
20
27
|
/**
|
|
@@ -29,8 +36,32 @@ export declare const ALL_DEFAULTS: DefaultPackage[];
|
|
|
29
36
|
* Exactly one mapper, always. `centerview()` is the only thing that moves the
|
|
30
37
|
* map view and only a mapper calls it, so a profile with no mapper never follows
|
|
31
38
|
* the player — and two mappers would both fire on the same movement.
|
|
39
|
+
*
|
|
40
|
+
* The starter UI is the one conditional pick: Mudlet skips it for players who
|
|
41
|
+
* aren't new (`experiencedMudletPlayer()` — any profile folder older than six
|
|
42
|
+
* months) because "veterans will have their own layouts already", and for games
|
|
43
|
+
* whose own loader installs a full interface. mudix has no profile-age signal to
|
|
44
|
+
* mirror the first, so `createdAt` stands in for it — see {@link isNewProfile}.
|
|
45
|
+
*/
|
|
46
|
+
export declare function stockDefaults(host?: string, conn?: {
|
|
47
|
+
createdAt?: string;
|
|
48
|
+
}): DefaultPackage[];
|
|
49
|
+
/**
|
|
50
|
+
* Whether a profile is new enough to be offered the starter UI.
|
|
51
|
+
*
|
|
52
|
+
* `addConnection` stamps `createdAt` on every profile it creates, so a profile
|
|
53
|
+
* without one was made before the field existed — i.e. someone has already been
|
|
54
|
+
* using it, quite possibly with a layout of their own. That's mudix's stand-in
|
|
55
|
+
* for Mudlet's "no profile folder older than six months" check: it errs the safe
|
|
56
|
+
* way, since dropping a dock, gauges and a chat window onto an established
|
|
57
|
+
* profile is far more disruptive than withholding them from a new one.
|
|
58
|
+
*
|
|
59
|
+
* No profile at all (tooling, a preview, `stockDefaults()` with no argument)
|
|
60
|
+
* counts as new — nothing established is at risk.
|
|
32
61
|
*/
|
|
33
|
-
export declare function
|
|
62
|
+
export declare function isNewProfile(conn?: {
|
|
63
|
+
createdAt?: string;
|
|
64
|
+
}): boolean;
|
|
34
65
|
/** A default or brand package as the install loop sees it. */
|
|
35
66
|
export type InstallablePackage = DefaultPackage & {
|
|
36
67
|
removable?: boolean;
|
|
@@ -42,7 +73,9 @@ export type InstallablePackage = DefaultPackage & {
|
|
|
42
73
|
* them — `[]` preinstalls nothing, and a brand shipping its own mapper simply
|
|
43
74
|
* doesn't list ours. Unset means no opinion: the stock defaults for this game.
|
|
44
75
|
*/
|
|
45
|
-
export declare function resolveDefaultPackages(brandPackages: InstallablePackage[] | undefined, host?: string
|
|
76
|
+
export declare function resolveDefaultPackages(brandPackages: InstallablePackage[] | undefined, host?: string, conn?: {
|
|
77
|
+
createdAt?: string;
|
|
78
|
+
}): InstallablePackage[];
|
|
46
79
|
/** Hostname `stockDefaults` matches its game lists against, lowercased. */
|
|
47
80
|
export declare function connectionHost(conn: {
|
|
48
81
|
mode?: string;
|
|
Binary file
|
|
Binary file
|