Skip to content

Latest commit

 

History

History
246 lines (173 loc) · 7.71 KB

File metadata and controls

246 lines (173 loc) · 7.71 KB

AI Assistant instructions for Mudlet

Project overview

Mudlet is a cross-platform MUD client built with Qt6 and C++20, providing scripting capabilities in Lua 5.1. The project emphasizes "powerful simplicity" - clean interface with deep customization options.

Core technologies

  • C++20 with Qt6 (minimum 6.8.2)
  • CMake build system (minimum 3.25.1)
  • Lua 5.1 scripting engine
  • Cross-platform: Windows, macOS, Linux

Project structure

  • src/ - main application source code
  • test/ - Unit tests for C++ core, written in Qt Test
  • src/mudlet-lua/tests/ - Unit tests covering the Lua API, written in Busted
  • 3rdparty/ - External dependencies and libraries
  • translations/ - Internationalization files
  • .github/workflows/ - Github Actions workflows

Coding standards

All files should end with a newline character at the end of the file.

C++ Conventions

In general: write modern C++20 code, but avoid C++ exceptions, templates, and concepts as those have performance/complexity considerations, avoiding which has made Mudlet the success it is today.

Use range-based for loops instead of iterator-based or index-based loops where appropriate.

See .github/CONTRIBUTING.md for the coding standards as well as the information below:

// Class names: PascalCase with 'T' prefix for main classes
class TConsole : public QWidget

// Member variables: camelCase with 'm' prefix
QString mProfileName;

// Qt signals/slots: camelCase
signals:
    void profileChanged(const QString& name);

QFlags and enums

When working with Qt Q_DECLARE_FLAGS types, always use the proper enum/flags type - never pass them as raw int:

// Good - uses the typed enum
void setServerOrigin(Host*, const Host::DiscordOptionFlag);
QMap<Host*, Host::DiscordOptionFlags> mServerOriginFlags;

// Bad - loses type safety
void setServerOrigin(Host*, int flag);
QMap<Host*, int> mServerOriginFlags;

String handling

// Use qsl() macro for string literals (defined as QStringLiteral)
QString objectName = qsl("timer(Host:%1)(TTimerId:%2)").arg(hostName, timerName);

// Prefer QString for UI, tr() for user-visible strings
QString displayText = tr("Connection failed: %1").arg(errorMessage);

// Always add contextual comments for translators using //:
//: Toast notification shown when user dismisses an editor tip banner
QString toastMessage = tr("Banner hidden. <a href='undo'>Undo</a>");
// In .ui files, set "notr" attribute to true for string literals which require no translation
<widget>
  <property name="text">
    <string notr="true">-</string>
  </property>
</widget>

Memory management

  • Use Qt's parent-child system for automatic cleanup for Qt classes
  • Otherwise, use C++ smart pointers for non-Qt classes

Include management

Minimize #include directives to reduce build times:

In header files (.h):

  • Only include what's needed for declarations in that header
  • Use forward declarations (class Foo;) when only pointers or references are used
  • Never include headers "just in case" - each include in a header propagates to all files that include it

In source files (.cpp):

  • Only include headers actually used in that file
  • When adding new code, verify you need each include you add
  • Don't copy includes from similar files without checking if they're needed

Forward declaration examples:

// In header: use forward declaration when only pointer/reference is needed
class Host;  // Forward declare instead of #include "Host.h"
class QCloseEvent;

class MyClass {
    Host* mpHost;  // Pointer - forward declaration sufficient
    void closeEvent(QCloseEvent* event);  // Pointer param - forward declaration sufficient
};

// In cpp: include the full header where the type is actually used
#include "Host.h"
#include <QCloseEvent>

Key architecture points

Mudlet is single-threaded - all profiles, triggers, and the Lua engine run on the main thread. The only exception is networking, which is automatically handled in the background by Qt.

Core classes (src/ directory)

  • mudlet.h/cpp - main application
  • Host.h/cpp - game connection management using profiles
  • ctelnet.h/cpp - telnet protocol handling
  • TConsole.h/cpp - text display and input
  • TLuaInterpreter.h/cpp - Lua scripting engine
  • TMap.h/cpp - mapping system
  • src/lua-function-list.json - autogenerated functions file, do not update

Lua API development

// Standard Lua function template
int TLuaInterpreter::functionName(lua_State* L)
{
    const QString param = getVerifiedString(L, __func__, 1, "parameter name");
    // ... implementation

    lua_pushboolean(L, true);
    return 1; // number of return values
}

Common patterns

Comments

Don't add comments for obvious code as that increases cognitive load on the reader. Only add comments in unintuitive situations to explain why something was done.

Error handling

// Qt-style error handling
if (!file.open(QIODevice::ReadOnly)) {
    qWarning() << "Failed to open file:" << file.errorString();
    return false;
}

UI components

  • Dialog classes use dlg*.h/cpp naming
  • Follow Qt's Model-View pattern
  • Use Qt's signal/slot mechanism for communication

Build system notes

  • Build system: CMake (handles platform-specific configurations). See https://wiki.mudlet.org/w/Compiling_Mudlet for instructions.
  • Check code quality with clang-tidy using .clang-tidy configuration file
  • Allow up to 10mins for a build - it can take a while

Code formatting

After editing any C++ files (.cpp, .h), run clang-format before committing:

clang-format -i path/to/edited/file.cpp path/to/edited/file.h

On macOS, use the Homebrew-installed LLVM version to ensure compatibility:

$(brew --prefix llvm)/bin/clang-format -i path/to/edited/file.cpp path/to/edited/file.h

The project uses the .clang-format configuration in the repo root. This ensures consistent code style across the codebase.

Static analysis

For complete setup instructions on how to run static analysis during a build see, see: https://wiki.mudlet.org/w/Compiling_Mudlet#Static_Analysis

Debugging options

src/CMakeLists.txt contains commented debugging defines for development (search "Debugging code inclusions"):

  • DEBUG_TELNET - Telnet protocol debugging
  • DEBUG_UTF8_PROCESSING - UTF-8 decoding messages
  • DEBUG_SGR_PROCESSING - ANSI color sequence debugging
  • DEBUG_WINDOW_HANDLING - UI window operations
  • And others for encoding, MXP, map autosave, etc.

Usage: Uncomment relevant target_compile_definitions(mudlet PRIVATE DEBUG_XXX) lines when debugging specific areas. Important: Do not commit uncommented debug lines to git.

Git

Do not force-push to remote branches.

Building on macOS

For complete setup instructions, see: https://wiki.mudlet.org/w/Compiling_Mudlet#Compiling_on_macOS

Essential build commands:

# Build
cd /path/to/Mudlet/build
# wait up to 10mins for a build
cmake ../../Mudlet -DCMAKE_PREFIX_PATH=`brew --prefix qt6`
make -j `sysctl -n hw.ncpu`

# Run Mudlet - use absolute path to avoid directory confusion
/path/to/Mudlet/build/src/mudlet.app/Contents/MacOS/mudlet

Building on Linux

For complete setup instructions, see: https://wiki.mudlet.org/w/Compiling_Mudlet

# cd to the right build directory
cd /path/to/Mudlet/build

# configure (only needed the first time)
cmake ../ -G Ninja

# Compile using this command and wait up to 10mins for a build. Cmake runs the build in parallel by default, no need to specify number of jobs:
cmake --build .

# Run Mudlet - it's a visual, desktop application
cd /path/to/Mudlet/build
./src/mudlet

Building on Windows

For complete setup instructions, see: https://wiki.mudlet.org/w/Compiling_Mudlet#Compiling_on_Windows