2   admin guide

This document is intended as a reference to the internals of the mudpy engine, its terminology, ontology/taxonomy and file format.

2.1   glossary

Here is an attempt at clarifying terms used throughout the mudpy project documentation, code comments, variable names and data files. In some cases, these words may take on a particular meaning distinct from their everyday conversational use, thus the need to elucidate.

account:

Element identifying a user and associating it with a password hash, preferences, privileges, connection history and a list of avatars.

actor:

Element representing a living being within the simulation (whether controlled by scripted mudpy routines or an actual user).

admin:

User who is trusted to invoke administrative commands.

archetype:

Element existing simply to provide facets which other elements inherit.

avatar:

Actor intended to be controlled by a user.

clone:

Element automatically derived from a template, rather than created through a manual process.

command:

Element describing an action which can be taken to control an avatar or the simulation itself, including help information and the privileges required to see and make use of it.

contents:

Facet listing other elements which have the current element as their location. This could be props and actors in a room, props carried or worn by an actor, or props inside another container prop.

element:

Basic building block of mudpy data. In memory, it exists as a group of similarly-named keys in a dict structure.

exit:

Facet representing a room's navigable connection to other rooms.

facet:

Piece of information which, when grouped together with others, makes up an element. In memory, it exists as a value (of any valid Python data type) associated with a dict key comprised of its parent element and a predefined keyword identifying its purpose.

location:

Facet identifying the parent element's relative position to other elements. Specifically, it identifies another element listing this one in its contents.

log:

List of informational messages about the operation of the mudpy engine. Entries include timestamps and a value indicating the message's relative importance. These are typically written to a file or sent to the system log, as well as displayed to connected admins. Recent entries are also kept in a memory buffer which can be queried and filtered by an admin after the fact.

menu:
prop:

Element describing the properties of an inanimate object within the simulation, including size, weight, contents and use-specific features.

room:

Element describing the properties of a place within the simulation, including terrain, weather, light levels, contents and exits.

simulation:

Virtual world in which actors, props and rooms exist, maintained by the mudpy engine and influenced through interaction by users.

template:

Element existing to provide facets which are copied by clones.

universe:

Set of all elements in the simulation. In memory, it is a dict indexing the facets of all elements.

user:

Real-world individual associated with an account.

2.2   data model

One of the primary goals for mudpy is to apply a consistent data model for all information, from configuration and preferences to accounts and world data. Individual pieces of information are called facets, and are grouped together into entities called elements. Elements are meant to be treated as loosely-typed objects (if it walks like a duck and talks like a duck...), while facets within them have predefined names and are strictly typed. This combination provides the ability to have facet inheritance among elements as a layered sieve.

The mudpy data model consists of a mix of persistent data (stored externally but cached in memory), and ephemeral data (cross-reference indexes which can be regenerated from it). For now, persistent data is stored externally in a tree-like hierarchy of text files starting from a main configuration file (usually named mudpy.conf), and cached in memory as a single python dict known as the universe. This default implementation, while memory-hungry, is planned so as to reduce the number of dict lookup operations performed to retrieve an individual piece of information.

2.2.1   namespaces

.
The universe is organized with a layered namespace using the period (.) symbol as a separator. It is rooted at "." and grows to the right with successive nodes. The right-most node must always be a facet, and the remainder of the series thus denotes the absolute name of an element within the universe (the second node from the right being the relative element name and the remaining nodes to the left are called the group).
.mudpy
Near the root of the universal namespace are a number of special elements and groups anchored within the .mudpy branch, which provide necessary configuration information and keep some basic elements from cluttering the rest of the tree.
.mudpy.actor
Where new actors with no specified storage destination are kept by default.
.mudpy.arch
Where the default archetype definitions are grouped together.
.mudpy.comm
Where the default command definitions are grouped together.
.mudpy.data
Defines default long-term storage locations for various groups.
.mudpy.facet
Defines default values and validation checks for every facet.
.mudpy.file
Defines filesystem-based backend storage meta data.
.mudpy.lang
Speech-specific configuration.
.mudpy.lim
Various aspects determining mudpy performance.
.mudpy.log
Configuration for logs.
.mudpy.menu
Where the default menu definitions are grouped together.
.mudpy.move
Defines vectors for exit directions.
.mudpy.net
Network socket configuration.
.mudpy.proc
Process-specific configuration.
.mudpy.prop
Where new props with no specified storage destination are kept by default.
.mudpy.room
Where new rooms with no specified storage destination are kept by default.
.mudpy.time
Timing-specific settings and scheduling for the main loop.

2.2.2   file format

Long-term storage is accomplished with a trivial format, using line terminators to separate arbitrarily-ordered records. The one major drawback to this format is that multi-line formatting of a single string value is only possible through the $(eol) and $(inc:filename) replacement macros. Each record consists of a key and a value separated by an equal sign (=), where the key is relative to the anchor specified by the parent file which loaded it. Special records can also exist to describe a data file's properties, and always begin with an exclamation mark (!). These are stored in the universe under the .mudpy.file group with elements named for escaped versions of the file path (. and : replaced by \. and \:) and the exclamation mark stripped from the beginning of each facet.

!
Arbitrary string providing information about the file (commentary, copyright, et cetera).
!load
List of additional data sources to load and where to anchor their elements in the universe. The value is prefaced by the storage medium separated from the remainder by an optional parenthetical parameter and a colon. The only type implemented so far is file, and its only optional parameter is p (to denote those which should only be readable by the operating system user account under which the process is running rather than created with the default umask--ignored on unsupported platforms).
!lock
Boolean value indicating read-only status for the file.

2.2.3   comment lines

Lines begining with a pound symbol (#), with or without whitespace indentation, are ignored by the data loader and can be used to manually disable records or add comments. Empty lines or lines containing only whitespace are also ignored and can be used to separate groups of records if desired. The remaining lines are split at the first =, then independently stripped of any leading or trailing whitespace (so you can indent or tabulate records as you like). The left half of each becomes a unique key in the universe, and the right half is run through the eval() function before being assigned to that key in the dict. One side effect of the eval() function is that you can place comments at the ends of lines as long as you separate them from the value with a #, and they will be correctly ignored by the parser.

2.2.4   normalization

Note that any file not protected with a !lock record will be regenerated and rewritten by mudpy if its records are changed, so record format will be normalized and records reordered alphabetically. Extraneous whitespace (indentation/tabulation), trailing commentary, and any empty lines or lines beginning with # will be lost in this process as well. (This may be fixed at a later date.)

2.3   configuration

This reference covers configuration options which influence the operation of the mudpy engine, and should be comprehensive.

2.3.1   default data storage

.mudpy.data.*

(string, multiple) Everything in the key following ".mudpy.data" identifies a unique branch of the universe. The value designates where to save newly created nodes for long-term storage. The string begins with a method specification (for now, only "file" is implemented), followed by a colon (:) and then the storage location (file path/name). For the file method on Unix dericative platforms, an optional "(p)" can precede the : to indicate it should be private (readable only by the system user under which the mudpy process is running). Example:

.mudpy.data.mudpy.account = "file(p):/var/lib/mudpy/account"

2.3.2   (non-programming) language features

.mudpy.lang.actions

(dict, optional) This is used to tailor the appearance of output generated by the say command and its relatives, so as to add some readability and flavor. It matches a visible action to punctuation (ask, exclaim, et cetera). Example:

{ "?": "ask", "!": "exclaim", ".": "say" }
.mudpy.lang.default_punctuation

(string, optional) Unpunctuated statements made by actors should be assumed to terminate with this value. Example:

"."
.mudpy.lang.typos

(dict, optional) Replacements for common typographical and capitalization errors. Example:

{ "i": "I", "i'd": "I'd", "i'll": "I'll", "i'm": "I'm", "teh": "the" }

2.3.3   various configured limits

.mudpy.lim.admin

(string, optional) The first user to create an account named the same as this string will automatically be given full administrative privileges. Example:

"admin"
.mudpy.lim.avatars

(int, required) This is the maximum number of avatars allowed for each account. Example:

7
.mudpy.lim.backups

(int, optional) This is the number of backups to keep and rotate when overwriting data files. If unspecified or set to 0, no backup copies will be made. Example:

10
.mudpy.lim.password_tries

(int, required) This is the maximum number of password failures allowed during the login process. Once exceeded, the user will be disconnected. Example:

3

2.3.4   settings for logging

.mudpy.log.file

(string, optional) If set, log messages will be recorded to this file. Example:

"/var/log/mudpy.log"
.mudpy.log.lines

(int, optional) Number of log entries to keep in memory (the oldest are discarded)... If unset or 0, none will be written to mudpy's internal memory. Example:

1000
.mudpy.log.stdout
(bool, optional) If set to True, messages will be logged to the standard output of the mudpy process. If unspecified, the default is False.
.mudpy.log.syslog

(string, optional) If set, mudpy will send messages to the system log, and under the name specified by this value (Unix derivatives only). Example:

"mudpy"

2.3.5   movement definitions

.mudpy.move.*.enter_term

(string, multiple) Word or words describing the direction from where you are seen to enter the next room when moving. Example:

move.east.enter_term = "the west"
.mudpy.move.*.exit_term

(string, multiple) Word or words describing the direction where you are seen to exit the current room when moving. Example:

move.east.exit_term = "to the east"
.mudpy.move.*.vector

(tuple, multiple) Vector of signed integer units for use in vector addition to derive the destination coordinates from the current coordinates when moving through a gridlink exit. The example coordinate system used is left handed (east, north and up are positive, west, south and down are negative) and three-dimensional with a tuple component order of (longitude, latitude, altitude). Example:

move.east.vector = ( 1, 0, 0 )

2.3.6   network socket configuration

.mudpy.net.host

(string, optional) The IP address on which to listen. If unspecified, the default is all available addresses. Example:

"127.0.0.1"
.mudpy.net.port

(int, required) The TCP port on which to listen. Example:

4000

2.3.7   process settings

.mudpy.proc.daemon
(bool, optional) If set to True, mudpy will immediately fork and detach a child to become a daemon process, then close all open file descriptors and terminate the parent process (Unix derivatives only). The default value is False.
.mudpy.proc.pidfile

(string, optional) If set, this filename will contain the daemon's process ID (Unix derivatives only). Example:

"/var/run/mudpy.pid"

2.3.8   main loop timing parameters

.mudpy.time.idle.disconnect.*

(int, multiple) This value indicates the number of increments allowed to pass without input on a socket connection before it is terminated. This avoids accumulation of dead sockets which could otherwise max out the process' allowed file descriptors. The differentiators are either default or a state name used to override the default value for that specific state (active, entering_account_name, et cetera). Example:

6000
.mudpy.time.idle.warn.*

(int, multiple) This value indicates the number of increments allowed to pass without input on a socket connection before it is warned that termination is imminent. The differentiators are either default or a state name used to override the default value for that specific state. It is recommended that this be less than the corresponding .mudpy.time.idle.warn.* value. Example:

5000
.mudpy.time.increment

(float, required) This value indicates the number of seconds (or more commonly, fraction thereof) each pass through the main loop is intended to take. This roughly sets the frequency with which queued socket I/O operations are performed, pending events are triggered, and directly impacts the speed at which time passes in the simulation. Example:

0.1
.mudpy.time.log

(int, optional) Number of increments to wait between logging mudpy status messages. If unspecified or set to 0, no mudpy status messages will be written. Example:

6000
.mudpy.time.save

(int, required) Number of increments between updates of changed persistent data storage. Example:

600