github Mudlet/Mudlet Mudlet-4.22.0-ptb-2026-08-11-ed37c8ee
Public Test Build

pre-release4 hours ago

Changes since last PTB (Mudlet-4.22.0-ptb-2026-08-10-f1582ad8)

Fixed:

- underscores and descenders no longer clipped at certain font sizes #9743

- an empty XDG config directory hiding every profile #9712

Infrastructure:

- fix two tests still opting in with an empty XDG config dir #9810

- keep QTest's output visible when ctest runs on Windows #9751

- a media player no longer announces its own destruction #9746

- fix Windows CI losing the per-user luarocks tree #9752

Full changelog since last release (Mudlet-4.22.0)
Added:

- widget state getters for titles, stylesheets, tooltips and scroll bars #9645

- getWindowGeometry(), windowVisible() and getLabelText() functions #9528

- help links for packages, wired to the Module Help button #9453

- full-window background image/gradient support #9394

- starter interface with health bars, map and chat for new players #9454

- Federation 2 Community Edition #9500

- remainingNamedTimer() to check time left on a named timer #9411

- keyboard shortcuts to switch between game tabs #9460

- option to undo the game's own line wrapping #9455

- warn when two keyboard shortcuts clash #9449

- Show tutorial invitation on first launch #9169

- sign in to supported games using your browser (e.g. Google, Discord, or the game's own account) #9378

- feature callouts #9390

- UI tour to complement the Mudlet tutorial #9385

Improved:

- the starter UI's chat capture is now a trigger tree players can read and copy #9736

- OSC 8 hyperlink handling, and a setting to turn it off #9731

- credit seven more contributors in the About Mudlet dialog #9675

- make filler widget size in toolbars user settable #9332

- ship every default package as an mpackage #9626

- make the New profile button show what it did #9607

- do not copy leading spaces in multi-line select #9560

- split the games list into My games and All games tabs #9452

- honor XDG_CONFIG_HOME for Mudlet's config directory #9552

- show a simpler trigger editor by default #9450

- embed leak suppressions file in Mudlet binary #9465

- scripts can now match map menus with their map events #9443

- make keyboard shortcut settings work with screen readers #9322

- faster colour tag processing in cecho, decho and hecho #9426

Fixed:

- underscores and descenders no longer clipped at certain font sizes #9743

- an empty XDG config directory hiding every profile #9712

- MXP frames overlapping UI packages that reserve screen space #9737

- don't offer updates that don't yet have a sha256 sum #9735

- new profiles process game text about twice as fast #9705

- a profile named "." or ".." deletes every profile when removed #9722

- game text no longer loses a character to a stray escape code #9723

- triggers being deleted when a script creates a lot of them at once #9724

- macOS builds sometimes failing their tests for no reason #9733

- unbreak development - cloneExportDocument was renamed to takeExportDocument #9732

- getWindowGeometry() and windowVisible() answer for the main window #9714

- three full-window background bugs - vanishing console, lost border colour, huge cover scaling #9711

- two ways a profile save could lose or resurrect your data #9704

- three crashes in the game selection screen #9702

- four security holes in the new browser sign-in #9713

- pausing a track and then playing a different one left you with silence #9710

- mapper scripts stopped being told the map had opened #9709

- trigger editor and deleted item subtrees leaking memory #9700

- stop the test-only waitForEvent() wedging Mudlet on macOS #9691

- profile close during a map operation, Discord presence truncation, and interrupting ttsSpeak() #9686

- user key bindings on Ctrl+1 to Ctrl+9 and Ctrl+Tab #9703

- a trigger that re-creates itself freezes Mudlet #9697

- stop treating long-time Mudlet users as brand new players #9695

- module save reaching into the profile after it is destroyed #9690

- package lifecycle - queued save outliving the profile, unremovable archives, module priority #9684

- six command line and console bugs #9683

- temporary trigger/alias/key/timer cleanup evicting same-named items #9682

- eight Geyser layout and container bugs #9680

- four Lua API corrections - colours, room name offsets, map window state and printTable #9678

- stop the telnet reader writing a NUL past the data it was given #9677

- Mudlet freezing when a window is set to wrap too narrowly #9623

- Discord getters no longer treat presence text as a format string #9660

- don't replay a sign-in token the game already rejected #9676

- stop map saves polluting userData with fallback keys #9469

- Sounds going silent when a file fails to load #9612

- stop table.union modifying a table it was given #9613

- table.n_collect drops values that match an index #9615

- profiles with parentheses in their name can be opened again #9610

- removing a game's profile no longer hides it from the All Games list #9608

- compare() no longer rejects tables that hold false #9614

- event handlers no longer wipe the caller's Lua stack #9621

- killTrigger and killAlias report failure when the item is already dead #9620

- crash when opening settings on macOS #9625

- crash when closing Mudlet while an update is available #9604

- script error messages are readable in dark mode again #9606

- help banners no longer show up in the wrong editor section #9609

- Windows auto-update failing on a release binary with no checksum #9617

- strand no heap objects across the remaining lua_error() raises #9605

- tempTimer negative time, compile() error slot, killTimer idempotency #9597

- ttsSetVoiceByName return garbage and stale ttsSpeechStarted text #9595

- media start events fired too early when replaying a just-stopped sound #9611

- Geyser.Window:echo() keeps the stored message

- gauge three value CSS shorthand and non-positive maximums

- lay out new2 boxes, and apply the layout end_update deferred

- Geyser.Button:setState refuses 'down' before writing it

- Adjustable.Container resetTitle error and delete leaks

- setTextFormat leak, createLabel return convention, windowType scrollbox

- looping sounds playing only once #9569

- garbled error messages in networking and media functions #9551

- permGroup reports failure properly and listRemove removes consecutive duplicates #9550

- cap the length of inserted text like echoed text #9497

- ttsGetQueue out-of-bounds read and ttsClearQueue message #9471

- prevent a rare crash while saving a profile that uses modules #9559

- crash when a button uninstalls its own package #9558

- stop crashes while saving and profiles losing their triggers #9557

- replacing a temp item's script no longer keeps running the old function callback #9496

- clearing the screen no longer loses the last line from the log #9486

- variables added while playing are no longer lost when saving #9492

- highlight triggers no longer stop later color triggers from matching #9425

- getNamedTriggers no longer drops names when trigger types are mixed #9549

- replacing the game GUI download dialog no longer cancels the new download #9519

- scaleMovie collateral disconnect, isAnsi*Color returns, scrolling messages #9474

- colon-form underline styles now match other terminals #9498

- memory leak when perm* functions receive invalid Lua code #9556

- caret-mode Shift+Arrow selection off-by-one and Ctrl+C copy #9393

- bold text no longer brings back a colour the game already reset #9515

- exporting a package no longer destroys an existing file when you decline to overwrite #9495

- restarting to apply an update no longer leaves a second Mudlet running #9487

- harden the TLS-upgrade question against reconnects and profile closure #9518

- log no longer duplicates a line when logging is restarted #9490

- mapper API error reporting for getMapEvents and addRoom #9473

- color triggers now work inside 'only pass matches' trigger groups #9442

- triggers created by other triggers react to the current line again #9458

- flag invalid aliases and block loops while typing them #9499

- tempAnsiColorTrigger can match background colour only #9494

- MXP text now shows correctly on non-English games #9491

- non-English game text no longer garbles after a stray "&" #9489

- script output no longer breaks the game's colour and control codes #9485

- character-at-a-time warning misfires on password prompts #9391

- apply Discord API permission gating consistently #9472

- searchRoom returns nil+message for a missing roomID #9467

- tempButton and tempButtonToolbar return the created ID #9470

- remove duplicate cechoLink/dechoLink/hechoLink in GeyserMiniConsole #9477

- profile reset no longer forgets which variables to save #9484

- notepad arrows now visible in dark mode #9488

- align getTimestamp, getModulePriority, getModulePath failure returns #9480

- guard sendMSDP against disconnected/unnegotiated state #9478

- stop a malicious game from writing files outside the media folder #9504

- show connection details when picking a game on a fresh install #9451

- game information sent via MXP is no longer all-lowercase #9447

- 200 byte leak when loading a map #9464

- cap telnet subnegotiation length to bound memory use #9440

- recover from corrupt MCCP compression and stop losing data #9441

- stray ESC sequence no longer corrupts later text #9436

- script editor's info banner no longer glares in dark mode #9414

- script editor's search box no longer jumps around #9444

- keep non-ASCII characters in MXP custom entities #9439

- enforce the per-echo character limit #9438

- colon-form italic styling no longer corrupts underline #9437

- cap over-long escape sequences to bound memory use #9435

- hidden terminal control sequences no longer show up as text #9433

- certificate warnings now open settings for the right profile #9432

- package description images now work for packages with spaces in their name #9431

- tempAnsiColorTrigger now runs function callbacks #9427

- pasting several copied items now works for every item type #9423

- Variables view handles decimal numbers and true/false keys properly #9422

- editor copy/paste works after scripts create triggers or aliases #9421

- debug console shows its black background again #9419

- certificate warnings are now readable in dark mode #9418

- Copy button no longer oversized on the connection screen #9417

- main display no longer leaves a blank strip when the top border shrinks #9413

- word wrap changed by scripts now shows correctly in Preferences #9410

- clicking into the main window no longer steals copy from the command line #9305

- no more crash when viewing Variables after resetting a profile #9430

- deleting lines in triggers no longer corrupts the log file #9429

- save new modules to the location you choose #9424

- alias patterns no longer break after editing them #9420

- trigger editor's extra-options arrow is now visible in dark mode #9412

- Windows crash reports now show the actual cause #9370

- line-initial underscores no longer clipped at certain font sizes (regression of #7866) #9288

- updater not running on close, showing empty changelog #9388

- prevent crash from a trigger that endlessly feeds itself #9368

- variable editor keeps new variables nested in their parent table #9285

- trigger multi-line attribute resets when adding a sibling trigger #9284

- crash when a package uninstalls itself from its own alias/key/tr… #9383

- don't load a map if trying to create a mapper & map is already loaded #9415

- apply map label edits immediately in label preview #9387

- shrink preferences dialog to fit on 1377x768 screen #9407

- keep saved profile passwords working on Windows after qtkeychain library update #9395

- clickable links could show the wrong colours and styling after heavy output #9406

- add missing dictionary name #9400

- resize command line box for appendCmdLine/printCmdLine/clearCmdLine #9301

- console text not redrawing after resizing the window #9369

- editor keeps its maximized/full-screen state when toggled back to #9303

Infrastructure:

- fix two tests still opting in with an empty XDG config dir #9810

- keep QTest's output visible when ctest runs on Windows #9751

- a media player no longer announces its own destruction #9746

- fix Windows CI losing the per-user luarocks tree #9752

- keep the profile-removal file list from going stale #9739

- Bump lukka/get-cmake from 4.4.0 to 4.4.2 #9729

- tidy up how CI installs Lua #9734

- Update autocompletion data in Mudlet #9720

- Bump 3rdparty/sentry-native from a99d64e to a185ce8 #9727

- Bump 3rdparty/edbee-lib from a3ae51b to 62ca709 #9728

- Bump github/codeql-action from 4.37.3 to 4.37.6 #9730

- reject a release tag that does not match APP_VERSION #9701

- move module documents into their write jobs instead of copying #9699

- leak checking now gates the functional tests #9694

- Update text for translation in Crowdin #9718

- trim the comments left behind by two merged QA fixes #9708

- trim the comments around the experienced-player gate #9707

- assign milestones with the built-in token, not a PAT #9696

- fix milestone assignment, unbreak the key sequence tests #9679

- take re-entrancy depth counts off with scope guards #9687

- MMCP effect specs against a scripted chat peer #9629

- busted specs for the Geyser widget classes with no spec home #9665

- package and module lifecycle specs with a committed fixture kit #9632

- Discord effect specs against a fake Discord IPC server #9631

- cover the untested lua-lib surface #9630

- check mpackage archives match their sources #9624

- cut PR CI matrix in half and fix build flakes #9618

- make windows safe to destroy while a field has the text cursor #9596

- stop suppressing QString leaks in LSan enforcement #9602

- ignore multiple build targets #9562

- real-firing timer and script family Lua API tests #9572

- deepen the Geyser specs after test-coverage review

- address review of the Geyser specs

- Geyser geometry and visibility tests

- keep the HTTP fixtures byte-exact, harden the Windows step

- run the HTTP fixture server on Windows CI

- fix Windows media path assert, spare the media cache

- download, HTTP, media and TTS effect tests

- move media and TTS specs into Media_spec.lua

- drop attempt cap in setFont round-trip test

- window and label geometry/visibility Lua API tests

- document the LSan tracer-crash CI flake #9592

- decouple the mapper engine from UI dialogs #9513

- decouple profile management (Host) from UI dialogs #9514

- bump github/codeql-action from 4 to 4.37.3 #9565

- bump 3rdparty/sentry-native from a182754 to a99d64e #9564

- Update text for translation in Crowdin #9563

- document un-suppressible CI leak flakes #9561

- networking, MMCP, media and Discord API contract tests #9535

- replace test mocks with real API assertions; config, stopwatch and utils tests #9534

- database and datetime Lua API tests #9531

- add waitForEvent test helper for async Lua API tests #9527

- mock TTS engine and local HTTP server for tests #9529

- extensive mapper Lua API tests #9530

- ignore speech-dispatcher's one-time startup leak in leak detection #9521

- release resources in test fixture destructors #9522

- resolve CodeQL warnings in the telnet code #9523

- guard functional-test lookups with QVERIFY #9524

- clear 5 CodeQL warning-level alerts in src/ #9525

- re-enable Sentry crash reporting on PTB builds #9553

- survive xorg.freedesktop.org certificate expiry in CI #9554

- clean vestigial widget includes from the Lua engine files #9526

- trigger, alias, key and named-timer Lua API tests #9532

- UI text output and readback Lua API tests #9533

- decouple profile export and media playback from UI widgets #9512

- add performance baseline benchmark for the text and trigger pipeline #9509

- add Discord IPC server stub for end-to-end tests #9475

- harden the Widgets audit script and refresh its baseline #9516

- slim down the AI assistant instructions #9511

- harden the build for the minimum supported Qt version #9510

- add Qt Widgets dependency audit for the core library #9508

- decouple telnet engine from UI dialogs #9507

- use std::chrono literals for time durations #9493

- remove unregistered setMiniConsoleFontSize implementation #9479

- add profile and map save/load round-trip tests #9468

- Bump 3rdparty/sentry-native from 0f7802f to a182754 #9505

- Update sanitizers.cmake to latest upstream #9503

- Update text for translation in Crowdin #9502

- document how to record before & after demo videos #9482

- test suites no longer clash when run at the same time #9483

- stop known ASan leak noise failing the password migration test #9461

- memory leaks found during CI tests now fail the build #9481

- fix else-after-return in codebase #9096

- Bump actions/setup-node from 6 to 7 #9457

- Bump lukka/get-cmake from 4.3.4 to 4.4.0 #9456

- Update text for translation in Crowdin #9360

- PTBs shipping without all platforms' installers #9389

- add Mudlet lua files to those shown by Qt Creator #9409

- Bump 3rdparty/qtkeychain from 7718d0a to 875f77d #9399

- Bump 3rdparty/sentry-native from fea16b8 to 0f7802f #9398

- merge release-4.22 back into development #9386

Don't miss a new Mudlet release

NewReleases is sending notifications on new releases.