Skip to main content

Overview

Lich includes a built-in GTK3-based graphical interface for launching and managing game connections. The GUI provides an intuitive way to:
  • Select characters from saved accounts
  • Manage multiple game accounts
  • Configure connection settings
  • Launch scripts automatically
  • Manage passwords with encryption
Lich GTK Interface

Enabling the GUI

The GUI is enabled by default when GTK3 is available:
# GUI enabled (default)
lich --gui
lich

# Disable GUI (headless mode)
lich --no-gui
The GUI requires GTK3 to be installed. If GTK3 is not available, Lich automatically falls back to command-line mode.

Installation Requirements

Linux

Ubuntu/Debian
sudo apt-get install ruby-gtk3
Fedora/RHEL
sudo dnf install rubygem-gtk3
Arch
sudo pacman -S ruby-gtk3

macOS

brew install gtk+3
gem install gtk3

Windows

GTK3 Ruby bindings should be included with the Lich installer.

GUI Features

Account Management

The GUI allows you to save and manage multiple game accounts:
1

Add Account

Click “Add Account” and enter:
  • Account name
  • Password (encrypted storage)
  • Default front-end (Wizard, StormFront, etc.)
  • Default game (GemStone IV, DragonRealms, etc.)
2

Select Character

Characters from saved accounts appear in the dropdown
3

Launch

Click “Launch” to connect with the selected character

Password Encryption

The GUI supports three encryption modes:
Security Level: None ⚠️Passwords stored in plain text. Not recommended.
encryption: plaintext
account: MyAccount
password: MyPassword123
Password encryption modes can be configured from the GUI account management interface or via command-line options (see Configuration).

Game Selection

The GUI provides a dropdown for selecting your target game:
lib/common/gui/game_selection.rb
GAME_MAPPING = {
  'GS3' => 'GemStone IV',
  'GSX' => 'GemStone IV Platinum',
  'GST' => 'GemStone IV Prime Test',
  'GSF' => 'GemStone IV Shattered',
  'DR'  => 'DragonRealms',
  'DRX' => 'DragonRealms Platinum',
  'DRT' => 'DragonRealms Prime Test',
  'DRF' => 'DragonRealms Fallen'
}

Front-end Selection

Choose which front-end client to use:
  • Wizard - Legacy GSL-based client
  • StormFront - XML-based Windows client
  • Avalon - Alternative GSL client
  • Genie - DragonRealms XML client
  • Frostbite - Modern XML client

Auto-start Scripts

Configure scripts to launch automatically on login:
auto_start_scripts:
  - repository
  - go2
  - lnet
  - infomon

Dark Mode

Lich supports GTK’s dark theme:
# Enable dark mode
lich --dark-mode=true
lich --dark-mode=on

# Disable dark mode
lich --dark-mode=false
lich --dark-mode=off
Dark mode is applied via GTK settings:
lib/common/gtk.rb
if defined?(Gtk)
  @theme_state = Lich.track_dark_mode = true
  Gtk::Settings.default.gtk_application_prefer_dark_theme = true
end

Window Management

Window Persistence

The GUI remembers window size and position between sessions:
lib/common/gui/window_settings.rb
# Settings saved to: data/login_gui_settings.yml
settings = {
  width: 800,
  height: 600,
  position: [100, 100]
}

Multi-Monitor Support

Window positions are constrained to visible monitors:
lib/common/gui/window_settings.rb
# Ensures window appears on screen
def constrain_to_monitor(position, width, height)
  # Validates position is within monitor bounds
end

macOS Menu Bar Offset

On macOS, the GUI accounts for the menu bar:
lib/common/gui/window_settings.rb
DARWIN_SPACER = 28  # pixels

# Apply offset on macOS
spacer = darwin? ? DARWIN_SPACER : 0
window.move(x, y + spacer)

Accessibility Features

The GUI implements accessibility support:
lib/common/gui/accessibility.rb
# Make combo box accessible to screen readers
Accessibility.make_combo_accessible(
  combo,
  "Game Selection",
  "Select the game for this character"
)
This provides:
  • Screen reader labels
  • Keyboard navigation
  • Focus management
  • ARIA attributes

GTK Queue for Thread Safety

GTK operations must run on the main thread:
lib/common/gtk.rb
if defined?(Gtk)
  def Gtk.queue(&block)
    GLib::Timeout.add(1) {
      begin
        block.call
      rescue StandardError => e
        Lich.log "error in Gtk.queue: #{e}"
      end
      false  # don't repeat timeout
    }
  end
end

Usage in Scripts

# Safe GTK operations from any thread
Gtk.queue {
  window = Gtk::Window.new(:toplevel)
  window.title = "My Script Window"
  window.show_all
}
Calling GTK methods directly from non-main threads will cause segmentation faults. Always use Gtk.queue when updating the GUI from scripts.

Custom GUI Windows

Scripts can create custom GTK windows:
Gtk.queue {
  window = Gtk::Window.new(:toplevel)
  window.title = "Script Config"
  window.set_default_size(400, 300)
  
  # Create vertical box layout
  vbox = Gtk::Box.new(:vertical, 5)
  window.add(vbox)
  
  # Add label
  label = Gtk::Label.new("Configuration Options")
  vbox.pack_start(label, expand: false, fill: false, padding: 5)
  
  # Add button
  button = Gtk::Button.new(label: "Save")
  button.signal_connect('clicked') {
    echo "Button clicked!"
  }
  vbox.pack_start(button, expand: false, fill: false, padding: 5)
  
  window.show_all
}

Logo and Branding

Lich includes an embedded logo:
lib/common/gtk.rb
Gtk.queue {
  @default_icon = GdkPixbuf::Pixbuf.new(file: 'logo.png')
}
The logo appears in:
  • Window title bars
  • Task bars
  • Alt+Tab switchers

Troubleshooting

GUI Won’t Start

1

Check GTK3 Installation

ruby -e "require 'gtk3'; puts Gtk::VERSION.join('.')"
Should print GTK version (e.g., “3.24.0”)
2

Check Display Environment

echo $DISPLAY  # Should show :0 or :1
If empty, you’re not in a graphical environment
3

Try Headless Mode

lich --no-gui --login=CharacterName
4

Check Logs

tail -f ~/lich/logs/lich.log
Look for GTK-related errors

Dark Mode Not Working

# Check if dark mode is enabled
if defined?(Gtk)
  puts Gtk::Settings.default.gtk_application_prefer_dark_theme
  # => should be true
end
If false, try:
lich --dark-mode=on

Window Position Issues

Delete saved settings to reset:
rm ~/lich/data/login_gui_settings.yml
The window will reappear at default position on next launch.

Segmentation Faults

Segfaults are usually caused by calling GTK from non-main threads. Always use Gtk.queue { } wrapper.
# WRONG - will crash
Thread.new {
  window = Gtk::Window.new(:toplevel)
}

# CORRECT - thread-safe
Thread.new {
  Gtk.queue {
    window = Gtk::Window.new(:toplevel)
  }
}

Disabling the GUI Permanently

To always run in headless mode:

Option 1: Shell Alias

~/.bashrc
alias lich='lich --no-gui'

Option 2: Wrapper Script

/usr/local/bin/lich-headless
#!/bin/bash
lich --no-gui "$@"

Option 3: Configuration File

Create a startup script that sets default options:
~/.lich/startup.rb
ARGV << '--no-gui' unless ARGV.include?('--gui')

Configuration

Command-line GUI options

Front-ends

Supported client applications

Configuration

Command-line options and setup

GTK3 Documentation

Official GTK3 Ruby bindings

Build docs developers (and LLMs) love