ToastStunt is a fork of the LambdaMOO / Stunt server. It has a number of features and improvements that were found useful while developing Miriani and ChatMud, a mostly complete list of which can be found below.
- Features
- ChangeLog
- Build Instructions
- Function Documentation
- ToastCore
- Support and Development
- Stunt Information
-
SQLite
-
Perl Compatible Regular Expressions (PCRE)
-
Simplex Noise
-
64-bit Integers (with the choice to fall back to 32-bit integers; $maxint and $minint set automatically)
-
HAProxy Source IP Rewriting (see notes below if you need to disable this)
-
User friendly traceback error messages
-
Networking improvements:
- IPv6 connection support
- Threaded DNS lookups
- Secure TLS connections in
listen()
andopen_network_connection()
-
Waifs:
- Call :recycle on waifs when they're destroyed
- A WAIF type (so typeof(some_waif) == WAIF)
- Waif dict patch (so waif[x] and waif[x] = y will call the :_index and :_set_index verbs on the waif)
- '-w' command line option to convert existing databases with a different waif type to the new waif type
waif_stats()
(show how many instances of each class of waif exist, how many waifs are pending recycling, and how many waifs in total exist)- Parser recognition for waif properties (e.g. thing.:property)
-
Basic threading support:
- background.cc (a library, of sorts, to make it easier to thread builtins)
- Threaded builtins: sqlite_query, sqlite_execute, locate_by_name, sort, argon2, argon2_verify, connection_name_lookup
- set_thread_mode (an argument of 0 will disable threading for all builtins in the current verb, 1 will re-enable, and no arguments will print the current mode)
thread_pool()
(database control over the the thread pools)
-
FileIO improvements:
- Faster reading
- Open as many files as you want, configurable with FILE_IO_MAX_FILES or $server_options.file_io_max_files
file_handles()
(returns a list of open files)file_grep()
(search for a string in a file (kind of FUP in FIO, don't tell))file_count_lines()
(counts the number of lines in a file)
-
Profiling and debugging:
finished_tasks()
(returns a list of the last X tasks to finish executing, including their total execution time) [see options.h below]- Set a maximum lag threshold (can be overridden with $server_options.task_lag_threshold) that, when exceeded, will make a note in the server log and call #0:handle_lagging_task with arguments: {callers, execution time}
- Include a map of defined variables for stack frames when being passed to
handle_uncaught_error
,handle_task_timeout
, andhandle_lagging_task
[see options.h below] - Optionally capture defined variables for running tasks by providing a true argument to
queued_tasks()
or a third true argument totask_stack()
.
-
Telnet:
- Capture IAC commands and pass them to listener:do_out_of_band_command() for the database to handle.
-
Stunt Improvements
- Primitive types:
- Support calling verbs on an object prototype ($obj_proto). Counterintuitively, this will only work for types of OBJ that are invalid. This can come in useful for un-logged-in connections (i.e. creating a set of convenient utilities for dealing with negative connections in-MOO).
- Maps:
maphaskey()
(check if a key exists in a map. Looks nicer than!(x in mapkeys(map))
and is faster when not dealing with hundreds of keys)
- Primitive types:
-
Options.h configuration:
- LOG_CODE_CHANGES (causes .program and set_verb_code to add a line to the server log indicating the object, verb, and programmer)
- OWNERSHIP_QUOTA (disable the server's builtin quota management)
- USE_ANCESTOR_CACHE (enable a cache of an object's ancestors to speed up property lookups)
- UNSAFE_FIO (skip character by character line verification, trading off potential safety for speed)
- LOG_EVALS (add an entry to the server log any time eval is called)
- ONLY_32_BITS (switch from 64-bit integers back to 32-bit)
- MAX_LINE_BYTES (unceremoniously close connections that send lines exceeding this value to prevent memory allocation panics)
- DEFAULT_LAG_THRESHOLD (the number of seconds allowed before a task is considered laggy and triggers #0:handle_lagging_task)
- SAVE_FINISHED_TASKS (enable the finished_tasks function and define how many tasks get saved by default) [default can be overridden with $server_options.finished_tasks_limit]
- THREAD_ARGON2 (enable threading of Argon2 functions)
- TOTAL_BACKGROUND_THREADS (number of threads created at runtime)
- DEFAULT_THREAD_MODE (default mode of threaded functions)
- SAFE_RECYCLE (change ownership of everything an object owns before recycling it)
- NO_NAME_LOOKUP (disable automatic DNS name resolution on new connections. Can be overridden with $server_options.no_name_lookup)
- PCRE_PATTERN_CACHE_SIZE (specifies how many PCRE patterns are cached)
- INCLUDE_RT_VARS (Include runtime environment variables in the stack argument for
handle_uncaught_error
,handle_task_timeout
, andhandle_lagging_task
)
-
Additional builtins:
- frandom (random floats)
- distance (calculate the distance between an arbitrary number of points)
- relative_heading (a relative bearing between two coordinate sets)
- memory_usage (total memory used, resident set size, shared pages, text, data + stack)
- ftime (precise time, including an argument for monotonic timing)
- locate_by_name (quickly locate objects by their .name property)
- usage (returns {load averages}, user time, system time, page reclaims, page faults, block input ops, block output ops, voluntary context switches, involuntary context switches, signals received)
- explode (serverified version of the LambdaCore verb on $string_utils)
- slice (serverified version of the LambdaCore verb on $list_utils)
- occupants (return a list of objects of parent parent, optionally with a player flag check)
- spellcheck (uses Aspell to check spelling)
- locations (recursive location function)
- clear_ancestor_cache (clears the ancestor cache manually)
- chr (return extended ASCII characters; characters that can corrupt your database are considered invalid)
- reseed_random (reseed the random number generator)
- yin (yield if needed. Replicates :suspend_if_needed and ticks_left() checks)
- sort (a significantly faster replacement for the :sort verb. Also allows for natural sort order and reverse sorting)
- recreate (fill holes created by recycle() by recreating valid objects with those object numbers)
- recycled_objects (return a list of all objects destroyed by calling recycle())
- next_recycled_object (return the next object available for recreation)
- reverse (reverse lists)
- all_members (return the indices of all instances of a type in a list)
- curl (return webpage as string)
- owned_objects (returns all valid objects owned by an object)
- connection_name_lookup (perform a DNS name lookup)
- connection_info (show detailed information about a particular connection)
- parse_ansi (parses color tags into their ANSI equivalents)
- remove_ansi (strips ANSI tags from strings)
-
Miscellaneous changes:
- .last_move (a map of an object's last location and the time() it moved)
- Sub-second fork and suspend
- Call 'do_blank_command' on listening objects when a blank command is issued
- Allow
"string" in "some other string"
as a shortcut for index() - Allow exec to set environment variables with a new argument
- Change the server log message when calling switch_player()
- Deprecation of
tonum()
in favor oftoint()
- Move #0.dump_interval to $server_options.dump_interval
- New argument to
notify()
to suppress the newline - Support object lists in
isa()
as well as an optional third argument to return the matching parent rather than simply true or false - New argument to
move()
to effectivelylistinsert()
the object into the destination's .contents - New argument to
is_member()
for controlling case sensitivity of equality comparisons. No third argument or a true value results in standard functionality; a false value as the third argument results in case not mattering at all - Update
random()
to accept a second optional argument for setting the maximum value returned. Including the second argument will treat the first argument as the minimum. - SIGUSR1 will close and reopen the logfile, allowing it to be rotated without restarting the server.
- '-m' command line option to clear all last_move properties in your database (and not set them again for the lifetime of the process).
- Build system is now CMake
- Boolean (BOOL) type
- Allow handling of SIGUSR signals in the database with
#0:handle_signal()
apt install build-essential bison gperf cmake libsqlite3-dev libaspell-dev libpcre3-dev nettle-dev g++ libcurl4-openssl-dev libargon2-dev libssl-dev
mkdir build && cd build
cmake ../
make -j2
emerge dev-db/sqlite app-text/aspell app-dicts/aspell-en app-crypt/argon2 cmake
mkdir build && cd build
cmake ../
make -j2
pkg install bison gperf gcc cmake sqlite3 aspell pcre nettle libargon2
mkdir build && cd build
cmake ../
make -j2
Installing dependencies requires Homebrew.
If using OpenSSL, you may have to export an environment variable before running CMake:
- Apple Silicon:
export PKG_CONFIG_PATH="/opt/homebrew/opt/openssl@3/lib/pkgconfig"
- Intel:
export PKG_CONFIG_PATH="/usr/local/opt/openssl@3/lib/pkgconfig"
brew install pcre aspell nettle cmake openssl argon2
mkdir build && cd build
cmake ../
make -j2
There are a few build options available to developers:
Build Option | Effect |
---|---|
Release | Optimizations enabled, warnings disabled. |
Debug | Optimizations disabled, debug enabled. |
Warn | Optimizations enabled, warnings enabled. (Previous default behavior) |
LeakCheck | Minimal optimizations enabled, debug enabled, and address sanitizer enabled. |
To change the build, use: cmake -D CMAKE_BUILD_TYPE:STRING=BuildNameHere ../
Due to the way proxy detection works, if you're connecting to your MOO from localhost, you won't see the login screen. This is a minor inconvenience and shouldn't affect your ability to actually use your MOO. However, if it bothers you, you can disable HAProxy rewriting:
@prop $server_options.proxy_rewrite 0
;load_server_options()
For support or collaborative discussions, you can join:
- Discord
- The 'toaststunt' channel in ChatMUD.