mirror of
https://github.com/evennia/evennia.git
synced 2026-03-16 21:06:30 +01:00
Added Sphinx (reST-style) conversion of Evennia documentation to docs/. This is an auto-generated conversion directly from the Wiki, so it's not custom-written in any way (will also make it easy to update). You need Sphinx to compile the sources into fancy pages. Supporting sphinx is to make documentation easier to print and view offline. Currently no sphinx src-code viewing is activated by default, it gives too many spurious errors (the converters are in the repo though if you're interested in experimenting). So for offline autodocs, doxygen is still to recommend.
This commit is contained in:
parent
5a2b9e27a0
commit
bd0079a39d
65 changed files with 9394 additions and 143 deletions
9
.hgignore
Normal file
9
.hgignore
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
# This specifies file types that mercurial should
|
||||
# ignore, defined on glob format.
|
||||
|
||||
syntax: glob
|
||||
|
||||
*.pyc
|
||||
*.swp
|
||||
*~
|
||||
*#
|
||||
80
README
80
README
|
|
@ -1,27 +1,10 @@
|
|||
|
||||
Evennia README (http://evennia.com)
|
||||
--------------
|
||||
-----------------------------------
|
||||
Evennia README
|
||||
(http://evennia.com)
|
||||
Alpha hg (mercurial) version
|
||||
-----------------------------------
|
||||
|
||||
- Aug 2011 - split evennia into portal + server for better reload /Griatch
|
||||
- May 2011 - all commands implemented, web client, contribs /Griatch
|
||||
- Aug 2010 - evennia devel merged into trunk /Griatch
|
||||
- May 2010 - merged ABOUT and README. Added Current status /Griatch
|
||||
- < 2010 (earlier revisions)
|
||||
|
||||
Contents:
|
||||
---------
|
||||
- Version
|
||||
- About Evennia
|
||||
- Current Status
|
||||
- Contact, Support and Development
|
||||
- Directory structure
|
||||
- Design Objectives
|
||||
- The Components
|
||||
|
||||
|
||||
Version
|
||||
-------
|
||||
Evennia Alpha SVN version
|
||||
|
||||
About Evennia
|
||||
-------------
|
||||
|
|
@ -37,8 +20,7 @@ bare-bones base for developers. Some of our main features are:
|
|||
(djangoproject.com)
|
||||
* Powerful an extremely extendable bare-bones base system
|
||||
|
||||
The essential points here are the web integration and the SQL backing via
|
||||
Django. The Django framework has database abstraction abilities that give us
|
||||
The Django framework has database abstraction abilities that give us
|
||||
many features free, such as:
|
||||
|
||||
* The codebase will run transparently on MySQL, SQLite, or Postgres
|
||||
|
|
@ -90,7 +72,7 @@ will not be backwards compatabile. Changes touch almost all
|
|||
parts of Evennia's innards, from the way Objects are handled
|
||||
to Events, Commands and Permissions.
|
||||
|
||||
|
||||
(Earlier revisions, with other maintainer, go back to 2005)
|
||||
|
||||
|
||||
Contact, Support and Development
|
||||
|
|
@ -132,7 +114,7 @@ evennia
|
|||
The two main directories you will spend most of your time in
|
||||
are src/ and game/ (probably mostly game/).
|
||||
|
||||
Basically src contains everything related to
|
||||
Basically src/ contains everything related to
|
||||
running the gritty stuff behind the scenes. Unless you are an
|
||||
Evennia developer you should normally make sure never to edit
|
||||
things in src/, since this is where we push new revisions that
|
||||
|
|
@ -156,49 +138,3 @@ and use them.
|
|||
With this little first orientation, you should head into the online
|
||||
Evennia wiki documentation to get going with the codebase.
|
||||
|
||||
|
||||
Design Objectives
|
||||
-----------------
|
||||
1) To create a barebones MU* server that serves as a great foundation
|
||||
for capable admins to craft their own respective games. It is not the
|
||||
intention to provide a full-fledged, ready-to-run base, rather Evennia
|
||||
is offering the means to make such games.
|
||||
|
||||
2) Development of games on Evennia must be easy for anyone with some
|
||||
degree of Python experience. Building needs to be easy, and per-room,
|
||||
per-object, and environmental customizations need to be simple to
|
||||
do. This is handled by use of normal Python classes transparently
|
||||
abstracting and wrapping the SQL backend. The user should not need to
|
||||
use SQL or even know Django to any greater extent.
|
||||
|
||||
3) The server must utilize SQL as a storage back-end to allow for web->game
|
||||
integration through Django.
|
||||
|
||||
The Components
|
||||
--------------
|
||||
Python (Including the SQL driver of your choice)
|
||||
|-Twisted (http://twistedmatrix.com)
|
||||
|-SQL (MySQL, SQLite, Postgresql)
|
||||
|-Django (http://djangoproject.com)
|
||||
|
||||
Evennia is built on top of Twisted, a networking engine that handles a lot
|
||||
of the guts and lower-level socket stuff for us.
|
||||
|
||||
Serving as our storage medium, SQL allows for very simple code in many cases, and
|
||||
can lead to a game being a lot more scalable due to the inherent speed of
|
||||
most modern SQL servers. Another extremely important benefit is that by
|
||||
storing everything in SQL, we make the entire game accessible from other
|
||||
means, such as a website. Which leads us to the next component.
|
||||
|
||||
Django is perhaps one of the most interesting introductions to the codebase.
|
||||
Django is technically a Python web framework, but it also includes a great
|
||||
data modeling and database abstraction module. This means that things like
|
||||
Players or Objects can be represented by a very short class, then related to one
|
||||
another. This allows us to add, remove, delete, and manipulate things in our database
|
||||
very easily. Another huge benefit is the admin interface that Django more
|
||||
or less automatically generates for us. Instead of a bunch of clunky admin
|
||||
commands, you can fire up your web browser and administer pretty much
|
||||
everything from there, although equivalent in-game commands may be offered.
|
||||
|
||||
The possibilities for developing your game's website are nearly endless with
|
||||
this tandem of MU* server, SQL, and Django.
|
||||
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
|||
SVN-Alpha
|
||||
HG-Alpha
|
||||
|
|
|
|||
50
docs/README
50
docs/README
|
|
@ -1,6 +1,7 @@
|
|||
|
||||
===========
|
||||
DOCS README
|
||||
-----------
|
||||
===========
|
||||
|
||||
* Evennia docs and manual
|
||||
|
||||
|
|
@ -17,9 +18,44 @@ DOCS README
|
|||
#evennia on the Freenode network
|
||||
|
||||
|
||||
* Evennia source auto-docs
|
||||
------------------------
|
||||
* Sphinx Manuals
|
||||
------------------------
|
||||
|
||||
The folder docs/sphinx contains a source tree with Evennia's online wiki
|
||||
formatted into reStructuredText for easy (and good looking!) offline
|
||||
browsing or printing.
|
||||
|
||||
To build the sources you need to install Sphinx. Linux users can get it
|
||||
through their package managers (in Debian it's called python-sphinx). Or
|
||||
you can download it here:
|
||||
|
||||
http://sphinx.pocoo.org/index.html
|
||||
|
||||
Go into docs/sphinx and run
|
||||
|
||||
make html
|
||||
|
||||
You will see a lot of output (and probably some errors too, Evennia's docs
|
||||
are not formatted to reST format by default). When done, point your
|
||||
web browser to docs/sphinx/build/html/index.html to see the nice manual.
|
||||
|
||||
In this folder you can build the developer auto-docs
|
||||
If you don't want html output, you can output to a host of other formats,
|
||||
use just "make" for a list of options.
|
||||
|
||||
|
||||
Note: In docs/sphinx are two more dirs, wiki2rest and src2rest. These
|
||||
can be used to create reST-formatted documentation from raw sources.
|
||||
They depend on a host of external libraries however, so best stay away
|
||||
from them unless you are an Evennia dev. Read the headers of the
|
||||
respective *.py files for instructions.
|
||||
|
||||
|
||||
-------------------
|
||||
* Doxygen auto-docs
|
||||
-------------------
|
||||
|
||||
In docs/doxygen you can build the developer auto-docs
|
||||
(a fancy searchable index of the entire source tree).
|
||||
This makes use of doxygen, a doc generator that parses
|
||||
the source tree and creates docs on the fly.
|
||||
|
|
@ -32,16 +68,16 @@ DOCS README
|
|||
|
||||
- Run
|
||||
|
||||
> doxygen Doxyfile
|
||||
> doxygen config.dox
|
||||
|
||||
This will create the auto-docs in a folder 'html'.
|
||||
This will create the auto-docs in a folder 'doxygen/html'.
|
||||
|
||||
- Start your web browser and point it to
|
||||
|
||||
<evenniadir>/docs/html/index.html
|
||||
<evenniadir>/docs/doxygen/html/index.html
|
||||
|
||||
- If you prefer a pdf version for printing, use LaTeX by
|
||||
activating the relevant section in Doxyfile. Run the
|
||||
activating the relevant section in config.dox. Run the
|
||||
doxygen command again as above and a new folder 'latex'
|
||||
will be created with the latex sources. With the latex
|
||||
processing system installed, then run
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
# Doxyfile 1.7.1
|
||||
# Doxyfile 1.7.4
|
||||
|
||||
# This file describes the settings to be used by the documentation system
|
||||
# doxygen (www.doxygen.org) for a project
|
||||
# doxygen (www.doxygen.org) for a project.
|
||||
#
|
||||
# All text after a hash (#) is considered a comment and will be ignored
|
||||
# All text after a hash (#) is considered a comment and will be ignored.
|
||||
# The format is:
|
||||
# TAG = value [value, ...]
|
||||
# For lists items can also be appended using:
|
||||
# TAG += value [value, ...]
|
||||
# Values that contain spaces should be placed between quotes (" ")
|
||||
# Values that contain spaces should be placed between quotes (" ").
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Project related configuration options
|
||||
|
|
@ -33,6 +33,19 @@ PROJECT_NAME = Evennia
|
|||
|
||||
PROJECT_NUMBER = SVN-Alpha
|
||||
|
||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||
# for a project that appears at the top of each page and should give viewer
|
||||
# a quick idea about the purpose of the project. Keep the description short.
|
||||
|
||||
PROJECT_BRIEF = Python MUD server
|
||||
|
||||
# With the PROJECT_LOGO tag one can specify an logo or icon that is
|
||||
# included in the documentation. The maximum height of the logo should not
|
||||
# exceed 55 pixels and the maximum width should not exceed 200 pixels.
|
||||
# Doxygen will copy the logo to the output directory.
|
||||
|
||||
PROJECT_LOGO = ../../src/web/media/images/evennia_logo_small.png
|
||||
|
||||
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
|
||||
# base path where the generated documentation will be put.
|
||||
# If a relative path is entered, it will be relative to the location
|
||||
|
|
@ -57,7 +70,7 @@ CREATE_SUBDIRS = YES
|
|||
# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
|
||||
# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
|
||||
# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
|
||||
# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak,
|
||||
# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak,
|
||||
# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
|
||||
|
||||
OUTPUT_LANGUAGE = English
|
||||
|
|
@ -86,7 +99,7 @@ REPEAT_BRIEF = YES
|
|||
# "The $name file" "is" "provides" "specifies" "contains"
|
||||
# "represents" "a" "an" "the"
|
||||
|
||||
ABBREVIATE_BRIEF =
|
||||
ABBREVIATE_BRIEF =
|
||||
|
||||
# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
|
||||
# Doxygen will generate a detailed section even if there is only a brief
|
||||
|
|
@ -114,7 +127,7 @@ FULL_PATH_NAMES = NO
|
|||
# If left blank the directory from which doxygen is run is used as the
|
||||
# path to strip.
|
||||
|
||||
STRIP_FROM_PATH =
|
||||
STRIP_FROM_PATH =
|
||||
|
||||
# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
|
||||
# the path mentioned in the documentation of a class, which tells
|
||||
|
|
@ -126,7 +139,7 @@ STRIP_FROM_PATH =
|
|||
STRIP_FROM_INC_PATH =
|
||||
|
||||
# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
|
||||
# (but less readable) file names. This can be useful is your file systems
|
||||
# (but less readable) file names. This can be useful if your file system
|
||||
# doesn't support long names like on DOS, Mac, or CD-ROM.
|
||||
|
||||
SHORT_NAMES = NO
|
||||
|
|
@ -193,7 +206,7 @@ OPTIMIZE_OUTPUT_FOR_C = NO
|
|||
# Java. For instance, namespaces will be presented as packages, qualified
|
||||
# scopes will look different, etc.
|
||||
|
||||
OPTIMIZE_OUTPUT_JAVA = YES
|
||||
OPTIMIZE_OUTPUT_JAVA = NO
|
||||
|
||||
# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
|
||||
# sources only. Doxygen will then generate output that is more tailored for
|
||||
|
|
@ -223,7 +236,7 @@ EXTENSION_MAPPING =
|
|||
# to include (a tag file for) the STL sources as input, then you should
|
||||
# set this tag to YES in order to let doxygen match functions declarations and
|
||||
# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
|
||||
# func(std::string) {}). This also make the inheritance and collaboration
|
||||
# func(std::string) {}). This also makes the inheritance and collaboration
|
||||
# diagrams that involve STL classes more complete and accurate.
|
||||
|
||||
BUILTIN_STL_SUPPORT = NO
|
||||
|
|
@ -241,7 +254,7 @@ SIP_SUPPORT = NO
|
|||
|
||||
# For Microsoft's IDL there are propget and propput attributes to indicate getter
|
||||
# and setter methods for a property. Setting this option to YES (the default)
|
||||
# will make doxygen to replace the get and set methods by a property in the
|
||||
# will make doxygen replace the get and set methods by a property in the
|
||||
# documentation. This will only work if the methods are indeed getting or
|
||||
# setting a simple type. If this is not the case, or you want to show the
|
||||
# methods anyway, you should set this option to NO.
|
||||
|
|
@ -263,6 +276,13 @@ DISTRIBUTE_GROUP_DOC = NO
|
|||
|
||||
SUBGROUPING = YES
|
||||
|
||||
# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and
|
||||
# unions are shown inside the group in which they are included (e.g. using
|
||||
# @ingroup) instead of on a separate page (for HTML and Man pages) or
|
||||
# section (for LaTeX and RTF).
|
||||
|
||||
INLINE_GROUPED_CLASSES = NO
|
||||
|
||||
# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
|
||||
# is documented as struct, union, or enum with the name of the typedef. So
|
||||
# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
|
||||
|
|
@ -279,10 +299,10 @@ TYPEDEF_HIDES_STRUCT = NO
|
|||
# For small to medium size projects (<1000 input files) the default value is
|
||||
# probably good enough. For larger projects a too small cache size can cause
|
||||
# doxygen to be busy swapping symbols to and from disk most of the time
|
||||
# causing a significant performance penality.
|
||||
# causing a significant performance penalty.
|
||||
# If the system has enough physical memory increasing the cache will improve the
|
||||
# performance by keeping more symbols in memory. Note that the value works on
|
||||
# a logarithmic scale so increasing the size by one will rougly double the
|
||||
# a logarithmic scale so increasing the size by one will roughly double the
|
||||
# memory usage. The cache size is given by this formula:
|
||||
# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
|
||||
# corresponding to a cache size of 2^16 = 65536 symbols
|
||||
|
|
@ -327,7 +347,7 @@ EXTRACT_LOCAL_METHODS = NO
|
|||
# extracted and appear in the documentation as a namespace called
|
||||
# 'anonymous_namespace{file}', where file will be replaced with the base
|
||||
# name of the file that contains the anonymous namespace. By default
|
||||
# anonymous namespace are hidden.
|
||||
# anonymous namespaces are hidden.
|
||||
|
||||
EXTRACT_ANON_NSPACES = NO
|
||||
|
||||
|
|
@ -337,14 +357,14 @@ EXTRACT_ANON_NSPACES = NO
|
|||
# various overviews, but no documentation section is generated.
|
||||
# This option has no effect if EXTRACT_ALL is enabled.
|
||||
|
||||
HIDE_UNDOC_MEMBERS = YES
|
||||
HIDE_UNDOC_MEMBERS = NO
|
||||
|
||||
# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
|
||||
# undocumented classes that are normally visible in the class hierarchy.
|
||||
# If set to NO (the default) these classes will be included in the various
|
||||
# overviews. This option has no effect if EXTRACT_ALL is enabled.
|
||||
|
||||
HIDE_UNDOC_CLASSES = YES
|
||||
HIDE_UNDOC_CLASSES = NO
|
||||
|
||||
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
|
||||
# friend (class|struct|union) declarations.
|
||||
|
|
@ -403,7 +423,7 @@ INLINE_INFO = YES
|
|||
# alphabetically by member name. If set to NO the members will appear in
|
||||
# declaration order.
|
||||
|
||||
SORT_MEMBER_DOCS = NO
|
||||
SORT_MEMBER_DOCS = YES
|
||||
|
||||
# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
|
||||
# brief documentation of file, namespace and class members alphabetically
|
||||
|
|
@ -438,6 +458,15 @@ SORT_GROUP_NAMES = NO
|
|||
|
||||
SORT_BY_SCOPE_NAME = NO
|
||||
|
||||
# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to
|
||||
# do proper type resolution of all parameters of a function it will reject a
|
||||
# match between the prototype and the implementation of a member function even
|
||||
# if there is only one candidate or it is obvious which candidate to choose
|
||||
# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen
|
||||
# will still accept a match between prototype and implementation in such cases.
|
||||
|
||||
STRICT_PROTO_MATCHING = NO
|
||||
|
||||
# The GENERATE_TODOLIST tag can be used to enable (YES) or
|
||||
# disable (NO) the todo list. This list is created by putting \todo
|
||||
# commands in the documentation.
|
||||
|
|
@ -468,10 +497,10 @@ GENERATE_DEPRECATEDLIST= YES
|
|||
ENABLED_SECTIONS =
|
||||
|
||||
# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
|
||||
# the initial value of a variable or define consists of for it to appear in
|
||||
# the initial value of a variable or macro consists of for it to appear in
|
||||
# the documentation. If the initializer consists of more lines than specified
|
||||
# here it will be hidden. Use a value of 0 to hide initializers completely.
|
||||
# The appearance of the initializer of individual variables and defines in the
|
||||
# The appearance of the initializer of individual variables and macros in the
|
||||
# documentation can be controlled using \showinitializer or \hideinitializer
|
||||
# command in the documentation regardless of this setting.
|
||||
|
||||
|
|
@ -487,7 +516,7 @@ SHOW_USED_FILES = YES
|
|||
# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
|
||||
# in the documentation. The default is NO.
|
||||
|
||||
SHOW_DIRECTORIES = YES
|
||||
SHOW_DIRECTORIES = NO
|
||||
|
||||
# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
|
||||
# This will remove the Files entry from the Quick Index and from the
|
||||
|
|
@ -549,7 +578,7 @@ WARN_IF_UNDOCUMENTED = YES
|
|||
|
||||
WARN_IF_DOC_ERROR = YES
|
||||
|
||||
# This WARN_NO_PARAMDOC option can be abled to get warnings for
|
||||
# The WARN_NO_PARAMDOC option can be enabled to get warnings for
|
||||
# functions that are documented, but have no documentation for their parameters
|
||||
# or return value. If set to NO (the default) doxygen will only warn about
|
||||
# wrong or incomplete parameter documentation, but not about the absence of
|
||||
|
|
@ -581,7 +610,7 @@ WARN_LOGFILE =
|
|||
# directories like "/usr/src/myproject". Separate the files or directories
|
||||
# with spaces.
|
||||
|
||||
INPUT = ../
|
||||
INPUT = ../../
|
||||
|
||||
# This tag can be used to specify the character encoding of the source files
|
||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
|
||||
|
|
@ -595,10 +624,11 @@ INPUT_ENCODING = UTF-8
|
|||
# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
|
||||
# and *.h) to filter out the source-files in the directories. If left
|
||||
# blank the following patterns are tested:
|
||||
# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
|
||||
# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
|
||||
# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh
|
||||
# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py
|
||||
# *.f90 *.f *.for *.vhd *.vhdl
|
||||
|
||||
FILE_PATTERNS =
|
||||
FILE_PATTERNS = *.py
|
||||
|
||||
# The RECURSIVE tag can be used to turn specify whether or not subdirectories
|
||||
# should be searched for input files as well. Possible values are YES and NO.
|
||||
|
|
@ -610,10 +640,10 @@ RECURSIVE = YES
|
|||
# excluded from the INPUT source files. This way you can easily exclude a
|
||||
# subdirectory from a directory tree whose root is specified with the INPUT tag.
|
||||
|
||||
EXCLUDE = docs
|
||||
EXCLUDE = docs */migrate/
|
||||
|
||||
# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
|
||||
# directories that are symbolic links (a Unix filesystem feature) are excluded
|
||||
# directories that are symbolic links (a Unix file system feature) are excluded
|
||||
# from the input.
|
||||
|
||||
EXCLUDE_SYMLINKS = NO
|
||||
|
|
@ -624,7 +654,7 @@ EXCLUDE_SYMLINKS = NO
|
|||
# against the file with absolute path, so to exclude all test directories
|
||||
# for example use the pattern */test/*
|
||||
|
||||
EXCLUDE_PATTERNS =
|
||||
EXCLUDE_PATTERNS =
|
||||
|
||||
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
|
||||
# (namespaces, classes, functions, etc.) that should be excluded from the
|
||||
|
|
@ -677,8 +707,8 @@ INPUT_FILTER =
|
|||
# filter if there is a match.
|
||||
# The filters are a list of the form:
|
||||
# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
|
||||
# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
|
||||
# is applied to all files.
|
||||
# info on how filters are used. If FILTER_PATTERNS is empty or if
|
||||
# non of the patterns match the file name, INPUT_FILTER is applied.
|
||||
|
||||
FILTER_PATTERNS =
|
||||
|
||||
|
|
@ -688,6 +718,14 @@ FILTER_PATTERNS =
|
|||
|
||||
FILTER_SOURCE_FILES = NO
|
||||
|
||||
# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
|
||||
# pattern. A pattern will override the setting for FILTER_PATTERN (if any)
|
||||
# and it is also possible to disable source filtering for a specific pattern
|
||||
# using *.ext= (so without naming a filter). This option only has effect when
|
||||
# FILTER_SOURCE_FILES is enabled.
|
||||
|
||||
FILTER_SOURCE_PATTERNS =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to source browsing
|
||||
#---------------------------------------------------------------------------
|
||||
|
|
@ -697,12 +735,12 @@ FILTER_SOURCE_FILES = NO
|
|||
# Note: To get rid of all source code in the generated output, make sure also
|
||||
# VERBATIM_HEADERS is set to NO.
|
||||
|
||||
SOURCE_BROWSER = YES
|
||||
SOURCE_BROWSER = NO
|
||||
|
||||
# Setting the INLINE_SOURCES tag to YES will include the body
|
||||
# of functions and classes directly in the documentation.
|
||||
|
||||
INLINE_SOURCES = YES
|
||||
INLINE_SOURCES = NO
|
||||
|
||||
# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
|
||||
# doxygen to hide any special comment blocks from generated source code
|
||||
|
|
@ -714,13 +752,13 @@ STRIP_CODE_COMMENTS = YES
|
|||
# then for each documented function all documented
|
||||
# functions referencing it will be listed.
|
||||
|
||||
REFERENCED_BY_RELATION = YES
|
||||
REFERENCED_BY_RELATION = NO
|
||||
|
||||
# If the REFERENCES_RELATION tag is set to YES
|
||||
# then for each documented function all documented entities
|
||||
# called/used by that function will be listed.
|
||||
|
||||
REFERENCES_RELATION = YES
|
||||
REFERENCES_RELATION = NO
|
||||
|
||||
# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
|
||||
# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
|
||||
|
|
@ -790,7 +828,13 @@ HTML_FILE_EXTENSION = .html
|
|||
|
||||
# The HTML_HEADER tag can be used to specify a personal HTML header for
|
||||
# each generated HTML page. If it is left blank doxygen will generate a
|
||||
# standard header.
|
||||
# standard header. Note that when using a custom header you are responsible
|
||||
# for the proper inclusion of any scripts and style sheets that doxygen
|
||||
# needs, which is dependent on the configuration options used.
|
||||
# It is adviced to generate a default header using "doxygen -w html
|
||||
# header.html footer.html stylesheet.css YourConfigFile" and then modify
|
||||
# that header. Note that the header is subject to change so you typically
|
||||
# have to redo this when upgrading to a newer version of doxygen or when changing the value of configuration settings such as GENERATE_TREEVIEW!
|
||||
|
||||
HTML_HEADER =
|
||||
|
||||
|
|
@ -809,6 +853,15 @@ HTML_FOOTER =
|
|||
|
||||
HTML_STYLESHEET =
|
||||
|
||||
# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
|
||||
# other source files which should be copied to the HTML output directory. Note
|
||||
# that these files will be copied to the base HTML output directory. Use the
|
||||
# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
|
||||
# files. In the HTML_STYLESHEET file, use the file name only. Also note that
|
||||
# the files will be copied as-is; there are no commands or markers available.
|
||||
|
||||
HTML_EXTRA_FILES =
|
||||
|
||||
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
|
||||
# Doxygen will adjust the colors in the stylesheet and background images
|
||||
# according to this color. Hue is specified as an angle on a colorwheel,
|
||||
|
|
@ -852,7 +905,7 @@ HTML_ALIGN_MEMBERS = YES
|
|||
# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
|
||||
# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
|
||||
|
||||
HTML_DYNAMIC_SECTIONS = YES
|
||||
HTML_DYNAMIC_SECTIONS = NO
|
||||
|
||||
# If the GENERATE_DOCSET tag is set to YES, additional index files
|
||||
# will be generated that can be used as input for Apple's Xcode 3
|
||||
|
|
@ -889,7 +942,7 @@ DOCSET_PUBLISHER_ID = org.doxygen.Publisher
|
|||
|
||||
# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
|
||||
|
||||
DOCSET_PUBLISHER_NAME = Evennia development team
|
||||
DOCSET_PUBLISHER_NAME = Publisher
|
||||
|
||||
# If the GENERATE_HTMLHELP tag is set to YES, additional index files
|
||||
# will be generated that can be used as input for tools like the
|
||||
|
|
@ -1011,8 +1064,10 @@ ECLIPSE_DOC_ID = org.doxygen.Project
|
|||
|
||||
DISABLE_INDEX = NO
|
||||
|
||||
# This tag can be used to set the number of enum values (range [1..20])
|
||||
# that doxygen will group on one line in the generated HTML documentation.
|
||||
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values
|
||||
# (range [0,1..20]) that doxygen will group on one line in the generated HTML
|
||||
# documentation. Note that a value of 0 will completely suppress the enum
|
||||
# values from appearing in the overview section.
|
||||
|
||||
ENUM_VALUES_PER_LINE = 4
|
||||
|
||||
|
|
@ -1029,7 +1084,7 @@ GENERATE_TREEVIEW = NO
|
|||
# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories,
|
||||
# and Class Hierarchy pages using a tree view instead of an ordered list.
|
||||
|
||||
USE_INLINE_TREES = YES
|
||||
USE_INLINE_TREES = NO
|
||||
|
||||
# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
|
||||
# used to set the initial width (in pixels) of the frame in which the tree
|
||||
|
|
@ -1058,6 +1113,26 @@ FORMULA_FONTSIZE = 10
|
|||
|
||||
FORMULA_TRANSPARENT = YES
|
||||
|
||||
# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax
|
||||
# (see http://www.mathjax.org) which uses client side Javascript for the
|
||||
# rendering instead of using prerendered bitmaps. Use this if you do not
|
||||
# have LaTeX installed or if you want to formulas look prettier in the HTML
|
||||
# output. When enabled you also need to install MathJax separately and
|
||||
# configure the path to it using the MATHJAX_RELPATH option.
|
||||
|
||||
USE_MATHJAX = NO
|
||||
|
||||
# When MathJax is enabled you need to specify the location relative to the
|
||||
# HTML output directory using the MATHJAX_RELPATH option. The destination
|
||||
# directory should contain the MathJax.js script. For instance, if the mathjax
|
||||
# directory is located at the same level as the HTML output directory, then
|
||||
# MATHJAX_RELPATH should be ../mathjax. The default value points to the
|
||||
# mathjax.org site, so you can quickly see the result without installing
|
||||
# MathJax, but it is strongly recommended to install a local copy of MathJax
|
||||
# before deployment.
|
||||
|
||||
MATHJAX_RELPATH = http://www.mathjax.org/mathjax
|
||||
|
||||
# When the SEARCHENGINE tag is enabled doxygen will generate a search box
|
||||
# for the HTML output. The underlying search engine uses javascript
|
||||
# and DHTML and should work on any modern browser. Note that when using
|
||||
|
|
@ -1073,7 +1148,7 @@ SEARCHENGINE = YES
|
|||
# using Javascript. Doxygen will generate the search PHP script and index
|
||||
# file to put on the web server. The advantage of the server
|
||||
# based approach is that it scales better to large projects and allows
|
||||
# full text search. The disadvances is that it is more difficult to setup
|
||||
# full text search. The disadvantages are that it is more difficult to setup
|
||||
# and does not have live searching capabilities.
|
||||
|
||||
SERVER_BASED_SEARCH = NO
|
||||
|
|
@ -1114,10 +1189,10 @@ MAKEINDEX_CMD_NAME = makeindex
|
|||
COMPACT_LATEX = NO
|
||||
|
||||
# The PAPER_TYPE tag can be used to set the paper type that is used
|
||||
# by the printer. Possible values are: a4, a4wide, letter, legal and
|
||||
# by the printer. Possible values are: a4, letter, legal and
|
||||
# executive. If left blank a4wide will be used.
|
||||
|
||||
PAPER_TYPE = a4wide
|
||||
PAPER_TYPE = a4
|
||||
|
||||
# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
|
||||
# packages that should be included in the LaTeX output.
|
||||
|
|
@ -1131,6 +1206,13 @@ EXTRA_PACKAGES =
|
|||
|
||||
LATEX_HEADER =
|
||||
|
||||
# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for
|
||||
# the generated latex document. The footer should contain everything after
|
||||
# the last chapter. If it is left blank doxygen will generate a
|
||||
# standard footer. Notice: only use this tag if you know what you are doing!
|
||||
|
||||
LATEX_FOOTER =
|
||||
|
||||
# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
|
||||
# is prepared for conversion to pdf (using ps2pdf). The pdf file will
|
||||
# contain links (just like the HTML output) instead of page references
|
||||
|
|
@ -1340,7 +1422,7 @@ MACRO_EXPANSION = NO
|
|||
EXPAND_ONLY_PREDEF = NO
|
||||
|
||||
# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
|
||||
# in the INCLUDE_PATH (see below) will be search if a #include is found.
|
||||
# pointed to by INCLUDE_PATH will be searched when a #include is found.
|
||||
|
||||
SEARCH_INCLUDES = YES
|
||||
|
||||
|
|
@ -1370,15 +1452,15 @@ PREDEFINED =
|
|||
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
|
||||
# this tag can be used to specify a list of macro names that should be expanded.
|
||||
# The macro definition that is found in the sources will be used.
|
||||
# Use the PREDEFINED tag if you want to use a different macro definition.
|
||||
# Use the PREDEFINED tag if you want to use a different macro definition that
|
||||
# overrules the definition found in the source code.
|
||||
|
||||
EXPAND_AS_DEFINED =
|
||||
|
||||
# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
|
||||
# doxygen's preprocessor will remove all function-like macros that are alone
|
||||
# on a line, have an all uppercase name, and do not end with a semicolon. Such
|
||||
# function macros are typically used for boiler-plate code, and will confuse
|
||||
# the parser if not removed.
|
||||
# doxygen's preprocessor will remove all references to function-like macros
|
||||
# that are alone on a line, have an all uppercase name, and do not end with a
|
||||
# semicolon, because these will confuse the parser if not removed.
|
||||
|
||||
SKIP_FUNCTION_MACROS = YES
|
||||
|
||||
|
|
@ -1434,9 +1516,8 @@ PERL_PATH = /usr/bin/perl
|
|||
# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
|
||||
# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
|
||||
# or super classes. Setting the tag to NO turns the diagrams off. Note that
|
||||
# this option is superseded by the HAVE_DOT option below. This is only a
|
||||
# fallback. It is recommended to install and use dot, since it yields more
|
||||
# powerful graphs.
|
||||
# this option also works with HAVE_DOT disabled, but it is recommended to
|
||||
# install and use dot, since it yields more powerful graphs.
|
||||
|
||||
CLASS_DIAGRAMS = YES
|
||||
|
||||
|
|
@ -1470,16 +1551,15 @@ HAVE_DOT = NO
|
|||
|
||||
DOT_NUM_THREADS = 0
|
||||
|
||||
# By default doxygen will write a font called FreeSans.ttf to the output
|
||||
# directory and reference it in all dot files that doxygen generates. This
|
||||
# font does not include all possible unicode characters however, so when you need
|
||||
# these (or just want a differently looking font) you can specify the font name
|
||||
# using DOT_FONTNAME. You need need to make sure dot is able to find the font,
|
||||
# By default doxygen will write a font called Helvetica to the output
|
||||
# directory and reference it in all dot files that doxygen generates.
|
||||
# When you want a differently looking font you can specify the font name
|
||||
# using DOT_FONTNAME. You need to make sure dot is able to find the font,
|
||||
# which can be done by putting it in a standard location or by setting the
|
||||
# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory
|
||||
# containing the font.
|
||||
|
||||
DOT_FONTNAME = FreeSans.ttf
|
||||
DOT_FONTNAME = Helvetica
|
||||
|
||||
# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
|
||||
# The default size is 10pt.
|
||||
|
|
@ -1554,7 +1634,7 @@ CALL_GRAPH = NO
|
|||
CALLER_GRAPH = NO
|
||||
|
||||
# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
|
||||
# will graphical hierarchy of all classes instead of a textual one.
|
||||
# will generate a graphical hierarchy of all classes instead of a textual one.
|
||||
|
||||
GRAPHICAL_HIERARCHY = YES
|
||||
|
||||
|
|
@ -1566,7 +1646,7 @@ GRAPHICAL_HIERARCHY = YES
|
|||
DIRECTORY_GRAPH = YES
|
||||
|
||||
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
|
||||
# generated by dot. Possible values are png, jpg, or gif
|
||||
# generated by dot. Possible values are svg, png, jpg, or gif.
|
||||
# If left blank png will be used.
|
||||
|
||||
DOT_IMAGE_FORMAT = png
|
||||
|
|
@ -1582,6 +1662,12 @@ DOT_PATH =
|
|||
|
||||
DOTFILE_DIRS =
|
||||
|
||||
# The MSCFILE_DIRS tag can be used to specify one or more directories that
|
||||
# contain msc files that are included in the documentation (see the
|
||||
# \mscfile command).
|
||||
|
||||
MSCFILE_DIRS =
|
||||
|
||||
# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
|
||||
# nodes that will be shown in the graph. If the number of nodes in a graph
|
||||
# becomes larger than this value, doxygen will truncate the graph, which is
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
twisted>=10.0
|
||||
django>=1.2.1
|
||||
PIL
|
||||
130
docs/sphinx/Makefile
Normal file
130
docs/sphinx/Makefile
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
# Makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS =
|
||||
SPHINXBUILD = sphinx-build
|
||||
PAPER =
|
||||
BUILDDIR = build
|
||||
|
||||
# Internal variables.
|
||||
PAPEROPT_a4 = -D latex_paper_size=a4
|
||||
PAPEROPT_letter = -D latex_paper_size=letter
|
||||
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
|
||||
|
||||
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
|
||||
|
||||
help:
|
||||
@echo "Please use \`make <target>' where <target> is one of"
|
||||
@echo " html to make standalone HTML files"
|
||||
@echo " dirhtml to make HTML files named index.html in directories"
|
||||
@echo " singlehtml to make a single large HTML file"
|
||||
@echo " pickle to make pickle files"
|
||||
@echo " json to make JSON files"
|
||||
@echo " htmlhelp to make HTML files and a HTML help project"
|
||||
@echo " qthelp to make HTML files and a qthelp project"
|
||||
@echo " devhelp to make HTML files and a Devhelp project"
|
||||
@echo " epub to make an epub"
|
||||
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
|
||||
@echo " latexpdf to make LaTeX files and run them through pdflatex"
|
||||
@echo " text to make text files"
|
||||
@echo " man to make manual pages"
|
||||
@echo " changes to make an overview of all changed/added/deprecated items"
|
||||
@echo " linkcheck to check all external links for integrity"
|
||||
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
|
||||
|
||||
clean:
|
||||
-rm -rf $(BUILDDIR)/*
|
||||
|
||||
html:
|
||||
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
||||
|
||||
dirhtml:
|
||||
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
|
||||
|
||||
singlehtml:
|
||||
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
|
||||
|
||||
pickle:
|
||||
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
|
||||
@echo
|
||||
@echo "Build finished; now you can process the pickle files."
|
||||
|
||||
json:
|
||||
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
|
||||
@echo
|
||||
@echo "Build finished; now you can process the JSON files."
|
||||
|
||||
htmlhelp:
|
||||
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run HTML Help Workshop with the" \
|
||||
".hhp project file in $(BUILDDIR)/htmlhelp."
|
||||
|
||||
qthelp:
|
||||
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
||||
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
|
||||
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Evennia.qhcp"
|
||||
@echo "To view the help file:"
|
||||
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Evennia.qhc"
|
||||
|
||||
devhelp:
|
||||
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
|
||||
@echo
|
||||
@echo "Build finished."
|
||||
@echo "To view the help file:"
|
||||
@echo "# mkdir -p $$HOME/.local/share/devhelp/Evennia"
|
||||
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Evennia"
|
||||
@echo "# devhelp"
|
||||
|
||||
epub:
|
||||
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
|
||||
@echo
|
||||
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
|
||||
|
||||
latex:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo
|
||||
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
|
||||
@echo "Run \`make' in that directory to run these through (pdf)latex" \
|
||||
"(use \`make latexpdf' here to do that automatically)."
|
||||
|
||||
latexpdf:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo "Running LaTeX files through pdflatex..."
|
||||
make -C $(BUILDDIR)/latex all-pdf
|
||||
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||
|
||||
text:
|
||||
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
|
||||
@echo
|
||||
@echo "Build finished. The text files are in $(BUILDDIR)/text."
|
||||
|
||||
man:
|
||||
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
|
||||
@echo
|
||||
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
|
||||
|
||||
changes:
|
||||
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
|
||||
@echo
|
||||
@echo "The overview file is in $(BUILDDIR)/changes."
|
||||
|
||||
linkcheck:
|
||||
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
|
||||
@echo
|
||||
@echo "Link check complete; look for any errors in the above output " \
|
||||
"or in $(BUILDDIR)/linkcheck/output.txt."
|
||||
|
||||
doctest:
|
||||
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
|
||||
@echo "Testing of doctests in the sources finished, look at the " \
|
||||
"results in $(BUILDDIR)/doctest/output.txt."
|
||||
170
docs/sphinx/make.bat
Normal file
170
docs/sphinx/make.bat
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
@ECHO OFF
|
||||
|
||||
REM Command file for Sphinx documentation
|
||||
|
||||
if "%SPHINXBUILD%" == "" (
|
||||
set SPHINXBUILD=sphinx-build
|
||||
)
|
||||
set BUILDDIR=build
|
||||
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% source
|
||||
if NOT "%PAPER%" == "" (
|
||||
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
|
||||
)
|
||||
|
||||
if "%1" == "" goto help
|
||||
|
||||
if "%1" == "help" (
|
||||
:help
|
||||
echo.Please use `make ^<target^>` where ^<target^> is one of
|
||||
echo. html to make standalone HTML files
|
||||
echo. dirhtml to make HTML files named index.html in directories
|
||||
echo. singlehtml to make a single large HTML file
|
||||
echo. pickle to make pickle files
|
||||
echo. json to make JSON files
|
||||
echo. htmlhelp to make HTML files and a HTML help project
|
||||
echo. qthelp to make HTML files and a qthelp project
|
||||
echo. devhelp to make HTML files and a Devhelp project
|
||||
echo. epub to make an epub
|
||||
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
|
||||
echo. text to make text files
|
||||
echo. man to make manual pages
|
||||
echo. changes to make an overview over all changed/added/deprecated items
|
||||
echo. linkcheck to check all external links for integrity
|
||||
echo. doctest to run all doctests embedded in the documentation if enabled
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "clean" (
|
||||
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
|
||||
del /q /s %BUILDDIR%\*
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "html" (
|
||||
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "dirhtml" (
|
||||
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "singlehtml" (
|
||||
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "pickle" (
|
||||
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can process the pickle files.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "json" (
|
||||
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can process the JSON files.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "htmlhelp" (
|
||||
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can run HTML Help Workshop with the ^
|
||||
.hhp project file in %BUILDDIR%/htmlhelp.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "qthelp" (
|
||||
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can run "qcollectiongenerator" with the ^
|
||||
.qhcp project file in %BUILDDIR%/qthelp, like this:
|
||||
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Evennia.qhcp
|
||||
echo.To view the help file:
|
||||
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Evennia.ghc
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "devhelp" (
|
||||
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "epub" (
|
||||
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The epub file is in %BUILDDIR%/epub.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "latex" (
|
||||
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "text" (
|
||||
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The text files are in %BUILDDIR%/text.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "man" (
|
||||
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The manual pages are in %BUILDDIR%/man.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "changes" (
|
||||
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.The overview file is in %BUILDDIR%/changes.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "linkcheck" (
|
||||
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Link check complete; look for any errors in the above output ^
|
||||
or in %BUILDDIR%/linkcheck/output.txt.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "doctest" (
|
||||
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Testing of doctests in the sources finished, look at the ^
|
||||
results in %BUILDDIR%/doctest/output.txt.
|
||||
goto end
|
||||
)
|
||||
|
||||
:end
|
||||
220
docs/sphinx/source/conf.py
Normal file
220
docs/sphinx/source/conf.py
Normal file
|
|
@ -0,0 +1,220 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Evennia documentation build configuration file, created by
|
||||
# sphinx-quickstart on Sat Sep 10 14:19:20 2011.
|
||||
#
|
||||
# This file is execfile()d with the current directory set to its containing dir.
|
||||
#
|
||||
# Note that not all possible configuration values are present in this
|
||||
# autogenerated file.
|
||||
#
|
||||
# All configuration values have a default; values that are commented out
|
||||
# serve to show the default.
|
||||
|
||||
import sys, os
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
|
||||
EVENNIA_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
sys.path.insert(0, EVENNIA_ROOT)
|
||||
sys.path.insert(0, os.path.dirname(EVENNIA_ROOT)) # also import top container
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'game.settings'
|
||||
|
||||
# -- General configuration -----------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
#needs_sphinx = '1.0'
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be extensions
|
||||
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.pngmath', 'sphinx.ext.ifconfig', 'sphinx.ext.viewcode']
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['.templates']
|
||||
|
||||
# The suffix of source filenames.
|
||||
source_suffix = '.rst'
|
||||
|
||||
# The encoding of source files.
|
||||
source_encoding = 'utf-8-sig'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = u'Evennia'
|
||||
copyright = u'2011, Evennia-development team'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = 'Alpha'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = 'Alpha'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
#language = None
|
||||
|
||||
# There are two options for replacing |today|: either, you set today to some
|
||||
# non-false value, then it is used:
|
||||
#today = ''
|
||||
# Else, today_fmt is used as the format for a strftime call.
|
||||
#today_fmt = '%B %d, %Y'
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
exclude_patterns = []
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all documents.
|
||||
#default_role = None
|
||||
|
||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||
#add_function_parentheses = True
|
||||
|
||||
# If true, the current module name will be prepended to all description
|
||||
# unit titles (such as .. function::).
|
||||
#add_module_names = True
|
||||
|
||||
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||
# output. They are ignored by default.
|
||||
#show_authors = False
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
|
||||
# A list of ignored prefixes for module index sorting.
|
||||
#modindex_common_prefix = []
|
||||
|
||||
|
||||
# -- Options for HTML output ---------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
html_theme = 'default'
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
#html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom themes here, relative to this directory.
|
||||
#html_theme_path = []
|
||||
|
||||
# The name for this set of Sphinx documents. If None, it defaults to
|
||||
# "<project> v<release> documentation".
|
||||
#html_title = None
|
||||
|
||||
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||
#html_short_title = None
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top
|
||||
# of the sidebar.
|
||||
#html_logo = None
|
||||
|
||||
# The name of an image file (within the static path) to use as favicon of the
|
||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||
# pixels large.
|
||||
#html_favicon = None
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['.static']
|
||||
|
||||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||
# using the given strftime format.
|
||||
#html_last_updated_fmt = '%b %d, %Y'
|
||||
|
||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||
# typographically correct entities.
|
||||
#html_use_smartypants = True
|
||||
|
||||
# Custom sidebar templates, maps document names to template names.
|
||||
#html_sidebars = {}
|
||||
|
||||
# Additional templates that should be rendered to pages, maps page names to
|
||||
# template names.
|
||||
#html_additional_pages = {}
|
||||
|
||||
# If false, no module index is generated.
|
||||
#html_domain_indices = True
|
||||
|
||||
# If false, no index is generated.
|
||||
#html_use_index = True
|
||||
|
||||
# If true, the index is split into individual pages for each letter.
|
||||
#html_split_index = False
|
||||
|
||||
# If true, links to the reST sources are added to the pages.
|
||||
#html_show_sourcelink = True
|
||||
|
||||
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
||||
#html_show_sphinx = True
|
||||
|
||||
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
||||
#html_show_copyright = True
|
||||
|
||||
# If true, an OpenSearch description file will be output, and all pages will
|
||||
# contain a <link> tag referring to it. The value of this option must be the
|
||||
# base URL from which the finished HTML is served.
|
||||
#html_use_opensearch = ''
|
||||
|
||||
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
||||
#html_file_suffix = None
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'Evenniadoc'
|
||||
|
||||
|
||||
# -- Options for LaTeX output --------------------------------------------------
|
||||
|
||||
# The paper size ('letter' or 'a4').
|
||||
#latex_paper_size = 'letter'
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#latex_font_size = '10pt'
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title, author, documentclass [howto/manual]).
|
||||
latex_documents = [
|
||||
('index', 'Evennia.tex', u'Evennia Documentation',
|
||||
u'Evennia-devs', 'manual'),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
# the title page.
|
||||
#latex_logo = None
|
||||
|
||||
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||
# not chapters.
|
||||
#latex_use_parts = False
|
||||
|
||||
# If true, show page references after internal links.
|
||||
#latex_show_pagerefs = False
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
#latex_show_urls = False
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#latex_preamble = ''
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#latex_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
#latex_domain_indices = True
|
||||
|
||||
|
||||
# -- Options for manual page output --------------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
('index', 'evennia', u'Evennia Documentation',
|
||||
[u'Evennia-devs'], 1)
|
||||
]
|
||||
84
docs/sphinx/source/index.rst
Normal file
84
docs/sphinx/source/index.rst
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
.. Evennia documentation master file, created by
|
||||
sphinx-quickstart on Sat Sep 10 14:19:20 2011.
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
Welcome to Evennia's documentation!
|
||||
===================================
|
||||
|
||||
This is `Evennia <http://www.evennia.com>`_'s sphinx-based
|
||||
documentation. It is built from the `online wiki <http://code.google.com/p/evennia/wiki/Index?tm=6>`_ at regular
|
||||
intervals.
|
||||
|
||||
|
||||
Text documentation
|
||||
-------------------
|
||||
.. toctree::
|
||||
:titlesonly:
|
||||
|
||||
Manual <wiki/Index>
|
||||
How to give and get help <wiki/HowToGetAndGiveHelp>
|
||||
Evennia Links <wiki/Links>
|
||||
|
||||
.. Code
|
||||
.. -----
|
||||
.. .. toctree::
|
||||
.. :titlesonly:
|
||||
|
||||
.. Browse Code <code/modules>
|
||||
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
|
||||
wiki/Index
|
||||
wiki/EvenniaIntroduction
|
||||
wiki/SoftCode
|
||||
wiki/GettingStarted
|
||||
wiki/AdminDocs
|
||||
wiki/ChoosingAnSQLServer
|
||||
wiki/StartStopReload
|
||||
wiki/UpdatingYourGame
|
||||
wiki/Internationalization
|
||||
wiki/StaffVersionControl
|
||||
wiki/ApacheConfig
|
||||
wiki/TextEncodings
|
||||
wiki/IRC
|
||||
wiki/IMC2
|
||||
wiki/BuilderDocs
|
||||
wiki/DefaultCommandHelp
|
||||
wiki/BuildingQuickstart
|
||||
wiki/BuildingPermissions
|
||||
wiki/Colours
|
||||
wiki/ConnectionScreen
|
||||
wiki/BatchProcessors
|
||||
wiki/BatchCommandProcessor
|
||||
wiki/BatchCodeProcessor
|
||||
wiki/TutorialWorldIntroduction
|
||||
wiki/DeveloperCentral
|
||||
wiki/Licensing
|
||||
wiki/Contributing
|
||||
wiki/UsingMUXAsAStandard
|
||||
wiki/BazaarDevel
|
||||
wiki/DirectoryOverview
|
||||
wiki/PortalAndServer
|
||||
wiki/Commands
|
||||
wiki/Typeclasses
|
||||
wiki/Objects
|
||||
wiki/Scripts
|
||||
wiki/Players
|
||||
wiki/Attributes
|
||||
wiki/Locks
|
||||
wiki/Communications
|
||||
wiki/HelpSystem
|
||||
wiki/Nicks
|
||||
wiki/SessionProtocols
|
||||
wiki/WebFeatures
|
||||
wiki/ExecutePythonCode
|
||||
wiki/UnitTesting
|
||||
wiki/RemovingColour
|
||||
wiki/CommandPrompt
|
||||
wiki/AsyncProcess
|
||||
wiki/WorkshopDefaultGame
|
||||
wiki/Workshop
|
||||
wiki/EvenniaDevel
|
||||
30
docs/sphinx/source/wiki/AdminDocs.rst
Normal file
30
docs/sphinx/source/wiki/AdminDocs.rst
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
Administrative Documentation
|
||||
============================
|
||||
|
||||
The following pages are aimed at game administrators. These are defined
|
||||
as the higher-ups that possess shell access and/or are responsible for
|
||||
the game.
|
||||
|
||||
Installation and Early Life
|
||||
---------------------------
|
||||
|
||||
- `Choosing an SQL Server <ChoosingAnSQLServer.html>`_
|
||||
- `Getting Started - Installing Evennia <GettingStarted.html>`_
|
||||
- `Starting, stopping, restarting and resetting
|
||||
Evennia <StartStopReload.html>`_
|
||||
- `Keeping your game up to date <UpdatingYourGame.html>`_
|
||||
- `Change Evennia's language <Internationalization.html>`_
|
||||
|
||||
<wiki:comment>
|
||||
|
||||
- `Collaborate with others using version
|
||||
control <StaffVersionControl.html>`_
|
||||
|
||||
</wiki:comment>
|
||||
|
||||
- `Apache Configuration <ApacheConfig.html>`_ (optional)
|
||||
- `Text encodings <TextEncodings.html>`_ used when connecting to
|
||||
Evennia
|
||||
- `How to connect Evennia to IRC channels <IRC.html>`_
|
||||
- `How to connect Evennia to an IMC2 network <IMC2.html>`_
|
||||
|
||||
117
docs/sphinx/source/wiki/ApacheConfig.rst
Normal file
117
docs/sphinx/source/wiki/ApacheConfig.rst
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
Apache Configuration
|
||||
====================
|
||||
|
||||
*OBS: Evennia has a powerful in-built Twisted-based web server for
|
||||
handling all web features. This works out of the box without any special
|
||||
setup. This page is only of interest if you really want/need to run
|
||||
Apache instead Evennia's in-built server. Note that the ajax web client
|
||||
is not guaranteed to work (at least not without tweaking) on a
|
||||
third-party server.*
|
||||
|
||||
The suggested third-party stack for running Evennia's web front end is
|
||||
`apache2 <http://httpd.apache.org/>`_ and
|
||||
`mod\_wsgi <http://code.google.com/p/modwsgi/>`_. However, the codebase
|
||||
may run just fine on other servers and modules (apache2/nginx/lighttpd +
|
||||
gunicorn, Tornado, uwsgi, etc.) Below are instructions on how to set
|
||||
things up with various apache2 Python modules. If you get things working
|
||||
using a different setup, please feel free to provide details below.
|
||||
|
||||
--------------
|
||||
|
||||
SQLite Note
|
||||
-----------
|
||||
|
||||
It's important to note that on Windows, you will be unable to run the
|
||||
game and your web presence at the same time due to evennia.db3 being
|
||||
locked while one has it opened. While Linux/Unix will let you run both
|
||||
concurrently, there **may** be issues with simultaneous read/writes by
|
||||
the game and the web front-end. The best bet to any game wishing to
|
||||
power their web presence with Evennia is to use Postgres, MySQL, Oracle,
|
||||
or any other supported full-blown relational database.
|
||||
|
||||
--------------
|
||||
|
||||
mod\_wsgi Setup
|
||||
---------------
|
||||
|
||||
Install mod\_wsgi
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
mod*wsgi is an excellent, secure, and high-performance way to serve
|
||||
Python projects. Code reloading is a breeze, Python modules are executed
|
||||
as a user of your choice (which is a great security win), and mod*wsgi
|
||||
is easy to set up on most distributions.
|
||||
|
||||
For the sake of brevity, this guide will refer you to mod\_wsgi's
|
||||
`installation
|
||||
instructions <http://code.google.com/p/modwsgi/wiki/InstallationInstructions>`_
|
||||
page, as their guides are great. For those that are running Debian or
|
||||
Ubuntu, you may install the entire stack with the following command:
|
||||
|
||||
``sudo aptitude install libapache2-mod-wsgi``
|
||||
|
||||
This should install apache2 (if it isn't already), mod*wsgi, and load
|
||||
the module. On Fedora or CentOS, you'll do this with ``yum`` and a
|
||||
similar package name that you'll need to search for. On Windows, you'll
|
||||
need to download and install apache2 and mod*wsgi binaries.
|
||||
|
||||
Copy and modify the VHOST
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
After mod\_wsgi is installed, copy the
|
||||
``evennia/game/web/utils/evennia_wsgi_apache.conf`` file to your apache2
|
||||
vhosts/sites folder. On Debian/Ubuntu, this is
|
||||
``/etc/apache2/sites-enabled/``. Make your modifications **after**
|
||||
copying the file there.
|
||||
|
||||
Read the comments and change the paths to point to the appropriate
|
||||
locations within your setup.
|
||||
|
||||
Restart/Reload Apache
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
You'll then want to reload or restart apache2. On Debian/Ubuntu, this
|
||||
may be done via:
|
||||
|
||||
``sudo /etc/init.d/apache2 restart`` or
|
||||
``sudo /etc/init.d/apache2 reload``
|
||||
|
||||
Enjoy
|
||||
~~~~~
|
||||
|
||||
With any luck, you'll be able to point your browser at your domain or
|
||||
subdomain that you set up in your vhost and see the nifty default
|
||||
Evennia webpage. If not, read the hopefully informative error message
|
||||
and work from there. Questions may be directed to our `Evennia Community
|
||||
site <http://evennia.com>`_.
|
||||
|
||||
A note on code reloading
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If your mod*wsgi is set up to run on daemon mode (as will be the case by
|
||||
default on Debian and Ubuntu), you may tell mod*wsgi to reload by using
|
||||
the ``touch`` command on ``evennia/game/web/utils/apache_wsgi.conf``.
|
||||
When mod\_wsgi sees that the file modification time has changed, it will
|
||||
force a code reload. Any modifications to the code will not be
|
||||
propagated to the live instance of your site until reloaded.
|
||||
|
||||
If you are not running in daemon mode or want to force the issue, simply
|
||||
restart or reload apache2 to apply your changes.
|
||||
|
||||
Further notes and hints:
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If you get strange (and usually uninformative) ``Permission denied``
|
||||
errors from Apache, make sure that your ``evennia`` directory is located
|
||||
in a place the webserver may actually access. For example, some Linux
|
||||
distributions may default to very restrictive access permissions on a
|
||||
user's ``/home`` directory.
|
||||
|
||||
One user commented that they had to add the following to their Apache
|
||||
config to get things to work. Not confirmed, but worth trying if there
|
||||
are trouble.
|
||||
|
||||
::
|
||||
|
||||
<Directory "/home/<yourname>/evennia/game/web"> Options +ExecCGI Allow from all </Directory>
|
||||
|
||||
130
docs/sphinx/source/wiki/AsyncProcess.rst
Normal file
130
docs/sphinx/source/wiki/AsyncProcess.rst
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
Asynchronous code
|
||||
=================
|
||||
|
||||
*This is considered an advanced topic, probably not useful for most
|
||||
users.*
|
||||
|
||||
Synchronous versus Asynchronous
|
||||
-------------------------------
|
||||
|
||||
Most code operate *synchronously*. This means that each statement in
|
||||
your code gets processed and finishes before the next can begin. This
|
||||
makes for easy-to-understand code. It is also a *requirement* in many
|
||||
cases - a subsequent piece of code often depend on something calculated
|
||||
or defined in a previous statement.
|
||||
|
||||
Consider this piece of code:
|
||||
|
||||
::
|
||||
|
||||
print "before call ..." long_running_function() print "after call ..."
|
||||
|
||||
When run, this will print ``"before call ..."``, after which the
|
||||
``long_running_function`` gets to work for however long time. Only once
|
||||
that is done, the system prints ``"after call ..."``. Easy and logical
|
||||
to follow. Most of Evennia work in this way. Most of the time we want to
|
||||
make sure that commands get executed in strict order after when they
|
||||
where entered.
|
||||
|
||||
The main problem is that Evennia is a multi-user server. It swiftly
|
||||
switches between dealing with player input in the order it is sent to
|
||||
it. So if one user, say, run a command containing that
|
||||
``long_running_function``, *all* other players are effectively forced to
|
||||
wait until it finishes ... hardly an ideal solution.
|
||||
|
||||
Now, it should be said that on a modern computer system this is rarely
|
||||
an issue. Very few commands run so long that other users notice it. And
|
||||
as mentioned, most of the time you *want* to enforce all commands to
|
||||
occur in strict sequence.
|
||||
|
||||
When delays do become noticeable and you don't care which order the
|
||||
command actually completes, you can run it *asynchronously*. This makes
|
||||
use of the ``run_async()`` function in ``src/utils/utils.py``.
|
||||
|
||||
::
|
||||
|
||||
from src.utils import utils print "before call ..." utils.run_async(long_running_function) print "after call ..."
|
||||
|
||||
Now, when running this you will find that the program will not wait
|
||||
around for ``long_running_function`` to finish. Infact you will see
|
||||
``"before call ..."`` and ``"after call ..."`` printed out right away.
|
||||
The long-running function will run in the background and you (and other
|
||||
users) can go on as normal.
|
||||
|
||||
Customizing asynchronous operation
|
||||
----------------------------------
|
||||
|
||||
A complication with using asynchronous calls is what to do with the
|
||||
result from that call. What if ``long_running_function`` returns a value
|
||||
that you need? It makes no real sense to put any lines of code after the
|
||||
call to try to deal with the result from ``long_running_function`` above
|
||||
- as we saw the ``"after call ..."`` got printed long before
|
||||
``long_running_function`` was finished, making that line quite pointless
|
||||
for processing any data from the function. Instead one has to use
|
||||
*callbacks*.
|
||||
|
||||
``utils.run_async`` takes two optional arguments, ``at_return`` and
|
||||
``at_err``. Both of these should be function defitions. Each will be
|
||||
called automatically.
|
||||
|
||||
- ``at_return(r)`` (the *callback*) is called when the asynchronous
|
||||
function (``long_running_function`` above) finishes successfully. The
|
||||
argument ``r`` will then be the return value of that function (or
|
||||
``None``). Example:
|
||||
|
||||
::
|
||||
|
||||
def at_return(r): print r
|
||||
|
||||
- ``at_err(e)`` (the *errback*) is called if the asynchronous function
|
||||
fails and raises an exception. This exception is passed to the
|
||||
errback wrapped in a *Failure* object ``e``. If you do not supply an
|
||||
errback of your own, Evennia will automatically add one that silently
|
||||
writes errors to the evennia log. An example of an errback is found
|
||||
below:
|
||||
|
||||
::
|
||||
|
||||
def at_err(e):
|
||||
print "There was an error:", str(e)
|
||||
|
||||
An example of making an asynchronous call from inside a
|
||||
`Command <Commands.html>`_ definition:
|
||||
|
||||
::
|
||||
|
||||
from src.utils import utils from game.gamesrc.commands.basecommand import Command class CmdAsync(Command): key = "asynccommand" def func(self): def long_running_function(): #[... lots of time-consuming code return final_value def at_return(r): self.caller.msg("The final value is %s" % r) def at_err(e): self.caller.msg("There was an error: %s" % e) # do the async call, setting all callbacks utils.run_async(long_running_function, at_return, at_err)
|
||||
|
||||
That's it - from here on we can forget about ``long_running_function``
|
||||
and go on with what else need to be done. *Whenever* it finishes, the
|
||||
``at_return`` function will be called and the final value will pop up
|
||||
for us to see. If not we will see an error message.
|
||||
|
||||
Assorted notes
|
||||
--------------
|
||||
|
||||
Be careful with choosing when to use asynchronous calls. It is mainly
|
||||
useful for large administration operations that has no direct influence
|
||||
on the game world (imports and backup operations come to mind). Since
|
||||
there is no telling exactly when an asynchronous call actually ends,
|
||||
using them for in-game commands is to potentially invite confusion and
|
||||
inconsistencies (and very hard-to-reproduce bugs).
|
||||
|
||||
The very first synchronous example above is not *really* correct in the
|
||||
case of Twisted, which is inherently an asynchronous server. Notably you
|
||||
might find that you will *not* see the first ``before call ...`` text
|
||||
being printed out right away. Instead all texts could end up being
|
||||
delayed until after the long-running process finishes. So all commands
|
||||
will retain their relative order as expected, but they may appear with
|
||||
delays or in groups.
|
||||
|
||||
Further reading
|
||||
---------------
|
||||
|
||||
Technically, ``run_async`` is just a very thin and simplified wrapper
|
||||
around a `Twisted
|
||||
Deferred <http://twistedmatrix.com/documents/9.0.0/core/howto/defer.html>`_
|
||||
object; the wrapper sets up a separate thread and assigns a default
|
||||
errback also if none is supplied. If you know what you are doing there
|
||||
is nothing stopping you from bypassing the utility function, building a
|
||||
more sophisticated callback chain after your own liking.
|
||||
166
docs/sphinx/source/wiki/Attributes.rst
Normal file
166
docs/sphinx/source/wiki/Attributes.rst
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
Attributes
|
||||
==========
|
||||
|
||||
When performing actions in Evennia it is often important that you store
|
||||
data for later. If you write a menu system, you have to keep track of
|
||||
the current location in the menu tree so that the player can give
|
||||
correct subsequent commands. If you are writing a combat system, you
|
||||
might have a combattant's next roll get easier dependent on if their
|
||||
opponent failed. Your characters will probably need to store
|
||||
roleplaying-attributes like strength and agility. And so on.
|
||||
|
||||
`Typeclassed <Typeclasses.html>`_ game entities
|
||||
(`Players <Players.html>`_, `Objects <Objects.html>`_ and
|
||||
`Scripts <Scripts.html>`_) always have *Attributes* associated with
|
||||
them. Attributes are used to store any type of data 'on' such entities.
|
||||
This is different from storing data in properties already defined on
|
||||
entities (such as ``key`` or ``location``) - these have very specific
|
||||
names and require very specific types of data (for example you couldn't
|
||||
assign a python *list* to the ``key`` property no matter how hard you
|
||||
tried). ``Attributes`` come into play when you want to assign arbitrary
|
||||
data to arbitrary names.
|
||||
|
||||
Saving and Retrieving data
|
||||
--------------------------
|
||||
|
||||
The **default** way of storing data on Typeclassed objects is simply to
|
||||
assign data to it. Let's try to save some data to a *Rose* (an
|
||||
`Object <Objects.html>`_):
|
||||
|
||||
::
|
||||
|
||||
# saving rose.has_thorns = True# getting it back is_ouch = rose.has_thorns
|
||||
|
||||
Whether this data is saved *persistently* to the database or not (i.e.
|
||||
if it survives a server reboot) depends on the setting of the variable
|
||||
``FULL_PERSISTENCE`` in the settings (it's described in more detail
|
||||
later on this page).
|
||||
|
||||
To be **sure** to save your data persistently, regardless of the setting
|
||||
of ``FULL_PERSISTENCE``, use the ``db`` (!DataBase) interface.
|
||||
|
||||
::
|
||||
|
||||
# saving rose.db.has_thorns = True # getting it back is_ouch = rose.db.has_thorns
|
||||
|
||||
This creates a new ``Attribute`` object and links it uniquely to
|
||||
``rose``. Using ``db`` ``will`` always save data to the database.
|
||||
|
||||
To be sure to save **non-persistently**, you use ``ndb`` (!NonDataBase).
|
||||
It works in the same way:
|
||||
|
||||
::
|
||||
|
||||
# saving rose.ndb.has_thorns = True # getting it back is_ouch = rose.ndb.has_thorns
|
||||
|
||||
(Using ``ndb`` like this will **NEVER** use the database.)
|
||||
|
||||
Strictly speaking, ``ndb`` has nothing to do with ``Attributes``,
|
||||
despite how similar they look. No ``Attribute`` object is created behind
|
||||
the scenes when using ``ndb``. In fact the database is not invoked at
|
||||
all since we are not interested in persistence.
|
||||
|
||||
You can also ``del`` properties on ``db`` and ``ndb`` as normal. This
|
||||
will for example delete an ``Attribute``:
|
||||
|
||||
::
|
||||
|
||||
del rose.db.has_thorns
|
||||
|
||||
Persistent vs non-persistent
|
||||
----------------------------
|
||||
|
||||
So *persistent* data means that your data will survive a server reboot,
|
||||
whereas with *non-persistent* data it will not ...
|
||||
|
||||
... So why would you ever want to use non-persistent data? The answer
|
||||
is, you don't have to. Most of the time you really want to save as much
|
||||
as you possibly can. Non-persistent data is potentially useful in a few
|
||||
situations though.
|
||||
|
||||
- You are worried about database performance. Maybe you are
|
||||
reading/storing data many times a second (for whatever reason) or you
|
||||
have many players doing things at the same time. Hitting the database
|
||||
over an over might not be ideal in that case. Non-persistent data
|
||||
simply writes to memory, it doesn't hit the database at all. With the
|
||||
speed and quality of hardware these days, this point is probably less
|
||||
likely to be of any big concern except for the most extreme of
|
||||
situations.
|
||||
- You *want* to loose your state when logging off. Maybe you are
|
||||
testing a buggy `Script <Scripts.html>`_ that does potentially
|
||||
harmful stuff to your character object. With non-persistent storage
|
||||
you can be sure that whatever the script messes up, it's nothing a
|
||||
server reboot can't clear up.
|
||||
- You want to implement a fully or partly *non-persistent world*.
|
||||
Whereas this sounds to us like something of an under-use of the
|
||||
codebase's potential, who are we to argue with your grand vision!
|
||||
|
||||
FULL\_PERSISTENCE
|
||||
-----------------
|
||||
|
||||
As mentioned above, Evennia allows you to change the default operation
|
||||
when storing attributes by using ``FULL_PERSISTENCE`` in
|
||||
``settings.py``.
|
||||
|
||||
With ``FULL_PERSISTENCE`` on, you can completely ignore ``db`` and
|
||||
assign properties to your object as you would any python object. This is
|
||||
the 'default' method shown at the top). Behind the scenes an
|
||||
``Attribute`` will be created and your data will be saved to the
|
||||
database. Only thing you have to do explicitly is if you *don't* want
|
||||
persistence, where you have to use ``ndb``.
|
||||
|
||||
With ``FULL_PERSISTENCE`` off, the inverse is true. You then have to
|
||||
specify ``db`` if you want to save, whereas normal assignment means
|
||||
non-persistence.
|
||||
|
||||
Regardless of the setting you can always use ``db`` and ``ndb``
|
||||
explicitly to get the result you want. This means writing a little bit
|
||||
more, but has the advantage of clarity and portability: If you plan to
|
||||
distribute your code to others, it's recommended you use explicit
|
||||
assignment. This avoids weird errors when your users don't happen to use
|
||||
the save persistence setting as you.
|
||||
|
||||
What types of data can I save?
|
||||
------------------------------
|
||||
|
||||
If you store a single object (that is, not a iterable list of objects),
|
||||
you can practically store any Python object that can be
|
||||
`pickled <http://docs.python.org/library/pickle.html>`_. Evennia uses
|
||||
the ``pickle`` module to serialize data into the database.
|
||||
|
||||
There is one notable type of object that cannot be pickled - and that is
|
||||
a Django database object. These will instead be stored as wrapper object
|
||||
containing the ID and its database model. It will be read back to a new
|
||||
instantiated `typeclass <Typeclasses.html>`_ when the Attribute is
|
||||
accessed. Since erroneously trying to save database objects in an
|
||||
Attribute will lead to errors, Evennia will try to detect database
|
||||
objects by analyzing the data being stored. This means that Evennia must
|
||||
recursively traverse all iterables to make sure all database objects in
|
||||
them are stored safely. So for efficiently, it can be a good idea is to
|
||||
avoid deeply nested lists with objects if you can.
|
||||
|
||||
To store several objects, you may only use python *lists* or
|
||||
*dictionaries* to store them. If you try to save any other form of
|
||||
iterable (like a ``set`` or a home-made class), the Attribute will
|
||||
convert, store and retrieve it as a list instead. Since you can nest
|
||||
dictionaries and lists together in any combination, this is usually not
|
||||
a limitation you need to worry about.
|
||||
|
||||
*Note that you could fool the safety check if you for example created
|
||||
custom, non-iterable classes and stored database objects in them. So to
|
||||
make this clear - saving such an object is **not supported** and will
|
||||
probably make your game unstable. Store your database objects using
|
||||
lists, dictionaries or a combination of the two and you should be fine.*
|
||||
|
||||
Examples of valid attribute data:
|
||||
|
||||
::
|
||||
|
||||
# a single value obj.db.test1 = 23 obj.db.test1 = False # a database object (will be stored as dbref) obj.db.test2 = myobj # a list of objects obj.db.test3 = [obj1, 45, obj2, 67] # a dictionary obj.db.test4 = 'str':34, 'dex':56, 'agi':22, 'int':77 # a mixed dictionary/list obj.db.test5 = 'members': [obj1,obj2,obj3], 'enemies':[obj4,obj5]# a tuple will stored and returned as a list [1,2,3,4,5]! obj.db.test6 = (1,2,3,4,5)
|
||||
|
||||
Notes
|
||||
-----
|
||||
|
||||
There are several other ways to assign Attributes to be found on the
|
||||
typeclassed objects, all being more 'low-level' underpinnings to
|
||||
``db``/``ndb``. Read their descriptions in the respective modules.
|
||||
200
docs/sphinx/source/wiki/BatchCodeProcessor.rst
Normal file
200
docs/sphinx/source/wiki/BatchCodeProcessor.rst
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
: Using the Evennia batch code processor
|
||||
|
||||
The Batch-Code processor
|
||||
========================
|
||||
|
||||
For an introduction and motivation to using batch processors, see
|
||||
`here <BatchProcessors.html>`_. This page describes the Batch-*code*
|
||||
processor. The Batch-*command* one is covered
|
||||
`here <BatchCommandProcessor.html>`_.
|
||||
|
||||
Basic Usage
|
||||
-----------
|
||||
|
||||
The batch-command processor is a superuser-only function, invoked by
|
||||
|
||||
::
|
||||
|
||||
> @batchcode path.to.batchcodefile
|
||||
|
||||
Where ``path.to.batchcodefile`` is the path to a *batch-code file* with
|
||||
the "``.py``" file ending. This path is given like a python path
|
||||
relative to a folder you define to hold your batch files, set by
|
||||
``BATCH_IMPORT_PATH`` in your settings. Default folder is
|
||||
``game/gamesrc/world``. So if you want to run the example batch file in
|
||||
``game/gamesrc/world/examples/batch_code.py``, you could simply use
|
||||
|
||||
::
|
||||
|
||||
> @batchcommand examples.batch_code
|
||||
|
||||
This will try to run through the entire batch file in one go. For more
|
||||
gradual, *interactive* control you can use the ``/interactive`` switch.
|
||||
The switch ``/debug`` will put the processor in *debug* mode. Read below
|
||||
for more info.
|
||||
|
||||
The batch file
|
||||
--------------
|
||||
|
||||
A batch-code file is mostly a normal Python source file. The only thing
|
||||
separating a batch file from any Python module is that the code are
|
||||
wrapped into *blocks* using a special syntax. These blocks allow the
|
||||
batch processor more control over execution, especially when using the
|
||||
processor's *interactive* mode, where they allow the default
|
||||
``@batchcommand`` to pause and only execute certain blocks at a time.
|
||||
|
||||
Here are the rules of syntax of the batch-command ``*.py`` file.
|
||||
|
||||
- ``#HEADER`` as the first on a line marks the start of a *header*
|
||||
block. This is intended to hold imports and variables that might be
|
||||
of use for for other blocks. All python code defined in a header
|
||||
block will always be inserted at the top of all ``#CODE`` blocks in
|
||||
the file. You may have more than one ``#HEADER`` block, but that is
|
||||
equivalent to having just one big one. Comments in ``#HEADER`` blocks
|
||||
are stripped out before merging.
|
||||
- ``#CODE`` as the first on a line marks the start of a *code* block.
|
||||
Code blocks contain functional python code. ``#HEADER`` blocks are
|
||||
added to the top of code blocks at runtime.
|
||||
- ``#CODE (info) obj1, obj2, ...`` is an optional form of the code
|
||||
block header. The ``(info)`` field gives extra info about what's
|
||||
going on in the block and is displayed by the batch processor. The
|
||||
``obj1, obj2, ...`` parts are optional object labels used by the
|
||||
processors *debug* mode in order to auto-delete objects after a test
|
||||
run.
|
||||
- A new ``#HEADER`` or ``#CODE`` (or the end of the file) ends the
|
||||
previous block. Text before the first block are ignored.
|
||||
- A ``#`` that is not starting a ``#HEADER`` or ``#CODE`` block is
|
||||
considered a comment.
|
||||
- Inside a block, normal Python syntax rules apply. For the sake of
|
||||
indentation, each block acts as a separate python module.
|
||||
- The variable ``caller`` is always made available to the script,
|
||||
pointing to the object executing the batchcommand.
|
||||
|
||||
Below is a version of the example file found in
|
||||
``game/gamesrc/commands/examples/batch_code.py``.
|
||||
|
||||
::
|
||||
|
||||
#
|
||||
# This is an example batch-code build file for Evennia.
|
||||
##HEADER# This will be included in all other #CODE blocksfrom src.utils import create, search from game.gamesrc.objects.examples import red_button from game.gamesrc.objects import baseobjectslimbo = search.objects(caller, 'Limbo', global_search=True)[0]#CODE (create red button)red_button = create.create_object(red_button.RedButton, key="Red button", location=limbo, aliases=["button"])# caller points to the one running the script caller.msg("A red button was created.")#CODE (create table and chair) table, chairtable = create.create_object(baseobjects.Object, key="Blue Table", location=limbo) chair = create.create_object(baseobjects.Object, key="Blue Chair", location=limbo)string = "A %s and %s were created. If debug was active, they were deleted again." caller.msg(string % (table, chair))
|
||||
|
||||
This uses Evennia's Python API to create three objects in sequence.
|
||||
|
||||
Debug mode
|
||||
----------
|
||||
|
||||
Try to run the example script with
|
||||
|
||||
::
|
||||
|
||||
> @batchcode/debug examples.batch_code
|
||||
|
||||
The batch script will run to the end and tell you it completed. You will
|
||||
also get messages that the button and the two pieces of furniture where
|
||||
created. Look around and you should see the button there. But you won't
|
||||
see any chair nor a table! This is because we ran this with the
|
||||
``/debug`` switch. The debug mode of the processor is intended to be
|
||||
used when you test out a script. Maybe you are looking for bugs in your
|
||||
code or try to see if things behave as they should. Running the script
|
||||
over and over would then create an ever-growing stack of buttons, chairs
|
||||
and tables, all with the same name. You would have to go back and
|
||||
painstakingly delete them later. The debug mode simply tries to
|
||||
automatically delete the objects that where created so as to not crowd
|
||||
the room with unwanted objects.
|
||||
|
||||
The second ``#CODE`` block supplies the variable names ``table`` and
|
||||
``chair``, which match the actual variables we later assign our new
|
||||
ojects to. In debug mode the batch-code processor will look for these
|
||||
references and simply run ``delete()`` on them. Since the
|
||||
button-creating block does not define any such variables the processor
|
||||
can't help us there - meaning the button stays also in debug mode.
|
||||
|
||||
Interactive mode
|
||||
----------------
|
||||
|
||||
Interactive mode works very similar to the `batch-command processor
|
||||
counterpart <BatchCommandProcessor.html>`_. It allows you more step-wise
|
||||
control over how the batch file is executed. This is useful for
|
||||
debugging or for picking and choosing only particular blocks to run. Use
|
||||
``@batchcommand`` with the ``/interactive`` flag to enter interactive
|
||||
mode.
|
||||
|
||||
::
|
||||
|
||||
> @batchcode/interactive examples.batch_code
|
||||
|
||||
You should see the following:
|
||||
|
||||
::
|
||||
|
||||
01/02: #CODE (create red button) [...] (hh for help)
|
||||
|
||||
This shows that you are on the first ``#CODE`` block, the first of only
|
||||
two commands in this batch file. Observe that the block has *not*
|
||||
actually been executed at this point!
|
||||
|
||||
To take a look at the full command you are about to run, use ``ll`` (a
|
||||
batch-processor version of ``look``).
|
||||
|
||||
::
|
||||
|
||||
from src.utils import create, search from game.gamesrc.objects.examples import red_button from game.gamesrc.objects import baseobjectslimbo = search.objects(caller, 'Limbo', global_search=True)[0]red_button = create.create_object(red_button.RedButton, key="Red button", location=limbo, aliases=["button"])# caller points to the one running the script caller.msg("A red button was created.")
|
||||
|
||||
Compare with the example code given earlier. Notice how the content of
|
||||
``#HEADER`` has been pasted at the top of the ``#CODE`` block. Use
|
||||
``pp`` to actually execute this block (this will create the button and
|
||||
give you a message). Use ``nn`` (next) to go to the next command. Use
|
||||
``hh`` for a list of commands.
|
||||
|
||||
If there are tracebacks, fix them in the batch file, then use ``rr`` to
|
||||
reload the file. You will still be at the same code block and can rerun
|
||||
it easily with ``pp`` as needed. This makes for a simple debug cycle. It
|
||||
also allows you to rerun individual troublesome blocks - as mentioned,
|
||||
in a large batch file this can be very useful (don't forget the
|
||||
``/debug`` mode either).
|
||||
|
||||
Use ``nn`` and ``bb`` (next and back) to step through the file; e.g.
|
||||
``nn 12`` will jump 12 steps forward (without processing any blocks in
|
||||
between). All normal commands of Evennia should work too while working
|
||||
in interactive mode.
|
||||
|
||||
Limitations and Caveats
|
||||
-----------------------
|
||||
|
||||
The batch-code processor is by far the most flexible way to build a
|
||||
world in Evennia. There are however some caveats you need to keep in
|
||||
mind.
|
||||
|
||||
- *Safety*. Or rather the lack of it. There is a reason only
|
||||
*superusers* are allowed to run the batch-code processor by default.
|
||||
The code-processor runs *without any Evennia security checks* and
|
||||
allows full access to Python. If an untrusted party could run the
|
||||
code-processor they could execute arbitrary python code on your
|
||||
machine, which is potentially a very dangerous thing. If you want to
|
||||
allow other users to access the batch-code processor you should make
|
||||
sure to run Evennia as a separate and very limited-access user on
|
||||
your machine (i.e. in a 'jail'). By comparison, the batch-command
|
||||
processor is much safer since the user running it is still 'inside'
|
||||
the game and can't really do anything outside what the game commands
|
||||
allow them to.
|
||||
- *You cannot communicate between code blocks*. Global variables won't
|
||||
work in code batch files, each block is executed as stand-alone
|
||||
environments. Similarly you cannot in one ``#CODE`` block assign to
|
||||
variables from the ``#HEADER`` block and expect to be able to read
|
||||
the changes from another ``#CODE`` block (whereas a python execution
|
||||
limitation, allowing this would also lead to very hard-to-debug code
|
||||
when using the interactive mode). The main issue with this is when
|
||||
building e.g. a room in one code block and later want to connect that
|
||||
room with a room you built in another block. To do this, you must
|
||||
perform a database search for the name of the room you created (since
|
||||
you cannot know in advance which dbref it got assigned). This sounds
|
||||
iffy, but there is an easy way to handler this - use object aliases.
|
||||
You can assign any number of aliases to any object. Make sure that
|
||||
one of those aliases is unique (like "room56") and you will
|
||||
henceforth be able to always find it later by searching for it from
|
||||
other code blocks regardless of if the main name is shared with
|
||||
hundreds of other rooms in your world (coincidentally, this is also
|
||||
one way of implementing "zones", should you want to group rooms
|
||||
together).
|
||||
|
||||
164
docs/sphinx/source/wiki/BatchCommandProcessor.rst
Normal file
164
docs/sphinx/source/wiki/BatchCommandProcessor.rst
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
: Using the Evennia command batch processors
|
||||
|
||||
The Batch-Command processor
|
||||
===========================
|
||||
|
||||
For an introduction and motivation to using batch processors, see
|
||||
`here <BatchProcessors.html>`_. This page describes the Batch-*command*
|
||||
processor. The Batch-*code* one is covered
|
||||
`here <BatchCodeProcessor.html>`_.
|
||||
|
||||
Basic Usage
|
||||
-----------
|
||||
|
||||
The batch-command processor is a superuser-only function, invoked by
|
||||
|
||||
::
|
||||
|
||||
> @batchcommand path.to.batchcmdfile
|
||||
|
||||
Where ``path.to.batchcmdfile`` is the path to a *batch-command file*
|
||||
with the "``.ev``" file ending. This path is given like a python path
|
||||
relative to a folder you define to hold your batch files, set with
|
||||
``BATCH_IMPORT_PATH`` in your settings. Default folder is
|
||||
``game/gamesrc/world``. So if you want to run the example batch file in
|
||||
``game/gamesrc/world/examples/batch_cmds.ev``, you could use
|
||||
|
||||
::
|
||||
|
||||
> @batchcommand examples.batch_cmds
|
||||
|
||||
A batch-command file contains a list of Evennia commands that you have
|
||||
previously entered. The processor will run the batch file from beginning
|
||||
to end. Note that *it will not stop if commands in it fail* (there is no
|
||||
universal way for the processor to know what a failure looks like for
|
||||
all different commands). So keep a close watch on the output, or use
|
||||
*Interactive mode* (see below) to run the file in a more controlled,
|
||||
gradual manner.
|
||||
|
||||
The batch file
|
||||
--------------
|
||||
|
||||
The batch file is a simple plain-text file containing Evennia commands.
|
||||
Just like you would write them in-game, except you have more freedom
|
||||
with line breaks.
|
||||
|
||||
Here's the rules of syntax of an ``*.ev`` file. You'll find it's really,
|
||||
really simple:
|
||||
|
||||
- All lines having the # (hash)-symbol *as the first one on the line*
|
||||
are considered *comments*.
|
||||
- Comments also have an actual function -- they mark the *end of the
|
||||
previous command definition*. So never put two commands directly
|
||||
after one another in the file - separate them with a comment, or the
|
||||
second of the two will be considered an argument to the first one
|
||||
(regardless, using plenty of comments is a good practice anyway).
|
||||
- Extra whitespace in a command definition are ignored. If you want a
|
||||
line break in texts, leave an empty line. Two empty lines thus means
|
||||
a new paragraph (for commands accepting formatting, that is).
|
||||
|
||||
Below is a version of the example file found in
|
||||
``game/gamesrc/commands/examples/batch_cmds.ev``.
|
||||
|
||||
::
|
||||
|
||||
# # This is an example batch build file for Evennia. ## This creates a red button button@create button:examples.red_button.RedButton# (This comment ends input for @create) # Next command. Let's create something. @set button/desc = This is a large red button. Now and then it flashes in an evil, yet strangely tantalizing way. A big sign sits next to it. It says:----------- Press me! ----------- ... It really begs to be pressed! You know you want to! # (This ends the @set command). Note that single line breaks # and extra whitespace in the argument are ignored. Empty lines # translate into line breaks in the output. # Now let's place the button where it belongs (let's say limbo #2 is # the evil lair in our example)@teleport #2# (This comments ends the @teleport command.) # Now we drop it so others can see it. # The very last command in the file needs not be ended with #.drop button
|
||||
|
||||
To test this, run ``@batchcommand`` on the file. A button will be
|
||||
created, described and dropped in Limbo. All commands will be executed
|
||||
by the user calling the command. *Note that if you interact with the
|
||||
button, you might find that its description changes, loosing your
|
||||
custom-set description above. This is just the way this particular
|
||||
object works.*
|
||||
|
||||
Interactive mode
|
||||
----------------
|
||||
|
||||
Interactive mode allows you to more step-wise control over how the batch
|
||||
file is executed. This is useful for debugging and also if you have a
|
||||
large batch file and is only updating a small part of it -- running the
|
||||
entire file again would be a waste of time (and in the case of
|
||||
``@create``-ing objects you would to end up with multiple copies of
|
||||
same-named objects, for example). Use ``@batchcommand`` with the
|
||||
``/interactive`` flag to enter interactive mode.
|
||||
|
||||
::
|
||||
|
||||
> @batchcommand/interactive examples.batch_cmds
|
||||
|
||||
You will see this:
|
||||
|
||||
::
|
||||
|
||||
01/04: @create button:examples.red_button.RedButton (hh for help)
|
||||
|
||||
This shows that you are on the ``@create`` command, the first out of
|
||||
only four commands in this batch file. Observe that the command
|
||||
``@create`` has *not* been actually processed at this point!
|
||||
|
||||
To take a look at the full command you are about to run, use ``ll`` (a
|
||||
batch-processor version of ``look``). Use ``pp`` to actually process the
|
||||
current command (this will actually ``@create`` the button) -- and make
|
||||
sure it worked as planned. Use ``nn`` (next) to go to the next command.
|
||||
Use ``hh`` for a list of commands.
|
||||
|
||||
If there are errors, fix them in the batch file, then use ``rr`` to
|
||||
reload the file. You will still be at the same command and can rerun it
|
||||
easily with ``pp`` as needed. This makes for a simple debug cycle. It
|
||||
also allows you to rerun individual troublesome commands - as mentioned,
|
||||
in a large batch file this can be very useful. Do note that in many
|
||||
cases, commands depend on the previous ones (e.g. if ``@create`` in the
|
||||
example above had failed, the following commands would have had nothing
|
||||
to operate on).
|
||||
|
||||
Use ``nn`` and ``bb`` (next and back) to step through the file; e.g.
|
||||
``nn 12`` will jump 12 steps forward (without processing any command in
|
||||
between). All normal commands of Evennia should work too while working
|
||||
in interactive mode.
|
||||
|
||||
Limitations and Caveats
|
||||
-----------------------
|
||||
|
||||
The batch-command processor is great for automating smaller builds or
|
||||
for testing new commands and objects repeatedly without having to write
|
||||
so much. There are several caveats you have to be aware of when using
|
||||
the batch-command processor for building larger, complex worlds though.
|
||||
|
||||
The main issue is that when you run a batch-command script you (*you*,
|
||||
as in your superuser character) are actually moving around in the game
|
||||
creating and building rooms in sequence, just as if you had been
|
||||
entering those commands manually, one by one. You have to take this into
|
||||
account when creating the file, so that you can 'walk' (or teleport) to
|
||||
the right places in order.
|
||||
|
||||
This also means there are several pitfalls when designing and adding
|
||||
certain types of objects. Here are some examples:
|
||||
|
||||
- *Rooms that changes your `cmdset <Commands.html>`_*: Imagine that you
|
||||
build a 'dark' room, which severely limits the cmdsets of those
|
||||
entering it (maybe you have to find the light switch to proceed). In
|
||||
your batch script you would create this room, then teleport to it -
|
||||
and promptly be shifted into the dark state where none of your normal
|
||||
build commands work ...
|
||||
- *Auto-teleportation*: Rooms that automatically teleport those that
|
||||
enter them to another place (like a trap room, for example). You
|
||||
would be teleported away too.
|
||||
- *Mobiles*: If you add aggressive mobs, they might attack you, drawing
|
||||
you into combat. If they have AI they might even follow you around
|
||||
when building - or they might move away from you before you've had
|
||||
time to finish describing and equipping them!
|
||||
|
||||
The solution to all these is to plan ahead. Make sure that superusers
|
||||
are never affected by whatever effects are in play. Add an on/off switch
|
||||
to objects and make sure it's always set to *off* upon creation. It's
|
||||
all doable, one just needs to keep it in mind.
|
||||
|
||||
Assorted notes
|
||||
--------------
|
||||
|
||||
The fact that you build as 'yourself' can also be considered an
|
||||
advantage however, should you ever decide to change the default command
|
||||
to allow others than superusers to call the processor. Since normal
|
||||
access-checks are still performed, a malevolent builder with access to
|
||||
the processor should not be able to do all that much damage (this is the
|
||||
main drawback of the `batch-code processor <BatchCodeProcessor.html>`_)
|
||||
103
docs/sphinx/source/wiki/BatchProcessors.rst
Normal file
103
docs/sphinx/source/wiki/BatchProcessors.rst
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
Batch Processors - overview
|
||||
===========================
|
||||
|
||||
Building a game world is a lot of work, especially when starting out.
|
||||
Rooms should be created, descriptions have to be written, objects must
|
||||
be detailed and placed in their proper places. In many traditional MUD
|
||||
setups you had to do all this online, line by line, over a telnet
|
||||
session.
|
||||
|
||||
Evennia already moves away from much of this by shifting the main coding
|
||||
work to external Python modules. But also building would be helped if
|
||||
one could do some or all of it externally. Enter Evennia's *batch
|
||||
command processors* (there are two of them). The processors allows you,
|
||||
as a game admin, to build your game completely offline in normal text
|
||||
files (*batch files*) that the processors understands. Then, when you
|
||||
are ready, you use the processors to read it all into Evennia (and into
|
||||
the database) in one go.
|
||||
|
||||
You can of course still build completely online should you want to -
|
||||
this is certainly the easiest way to go when learning and for small
|
||||
build projects. But for major building work, the advantages of using the
|
||||
batch-processors are many:
|
||||
|
||||
- It's hard to compete with the comfort of a modern desktop text
|
||||
editor; Compared to a traditional MUD line input, you can get much
|
||||
better overview and many more features. Also, accidentally pressing
|
||||
Return won't immediately commit things to the database.
|
||||
- You might run external spell checkers on your batch files. In the
|
||||
case of one of the batch-processors (the one that deals with Python
|
||||
code), you could also run external debuggers and code analyzers on
|
||||
your file to catch problems before feeding it to Evennia.
|
||||
- The batch files (as long as you keep them) are records of your work.
|
||||
They make a natural starting point for quickly re-building your world
|
||||
should you ever decide to start over.
|
||||
- If you are an Evennia developer, using a batch file is a fast way to
|
||||
setup a test-game after having reset the database.
|
||||
- The batch files might come in useful should you ever decide to
|
||||
distribute all or part of your world to others.
|
||||
|
||||
There are two batch processors, the Batch-*command* processor and the
|
||||
Batch-*code* processor. The first one is the simpler of the two. It has
|
||||
the advantage of you not needing to know any programming - you basically
|
||||
just list game commands in a text file. The code-processor on the other
|
||||
hand is much more powerful but also more complex - it lets you to use
|
||||
Evennia's API to code your world in full-fledged Python code.
|
||||
|
||||
- The `Batch-command processor <BatchCommandProcessor.html>`_
|
||||
- The `Batch-code processor <BatchCodeProcessor.html>`_
|
||||
|
||||
If you plan to use international characters in your batchfiles you are
|
||||
wise to read about *file encodings* below.
|
||||
|
||||
A note on File Encodings
|
||||
------------------------
|
||||
|
||||
As mentioned, both the processors take text files as input and then
|
||||
proceeds to process them. As long as you stick to the standard
|
||||
`ASCII <http://en.wikipedia.org/wiki/Ascii>`_ character set (which means
|
||||
the normal English characters, basically) you should not have to worry
|
||||
much about this section.
|
||||
|
||||
Many languages however use characters outside the simple ``ASCII``
|
||||
table. Common examples are various apostrophes and umlauts but also
|
||||
completely different symbols like those of the greek or cyrillic
|
||||
alphabets.
|
||||
|
||||
First, we should make it clear that Evennia itself handles international
|
||||
characters just fine. It (and Django) uses
|
||||
`unicode <http://en.wikipedia.org/wiki/Unicode>`_ strings internally.
|
||||
|
||||
The problem is that when reading a text file like the batchfile, we need
|
||||
to know how to decode the byte-data stored therein to universal unicode.
|
||||
That means we need an *encoding* (a mapping) for how the file stores its
|
||||
data. There are many, many byte-encodings used around the world, with
|
||||
opaque names such as ``Latin-1``, ``ISO-8859-3`` or ``ARMSCII-8`` to
|
||||
pick just a few examples. Problem is that it's practially impossible to
|
||||
determine which encoding was used to save a file just by looking at it
|
||||
(it's just a bunch of bytes!). You have to *know*.
|
||||
|
||||
With this little introduction it should be clear that Evennia can't
|
||||
guess but has to *assume* an encoding when trying to load a batchfile.
|
||||
The text editor and Evennia must speak the same "language" so to speak.
|
||||
Evennia will by default first try the international ``UTF-8`` encoding,
|
||||
but you can have Evennia try any sequence of different encodings by
|
||||
customizing the ``ENCODINGS`` list in your settings file. Evennia will
|
||||
use the first encoding in the list that do not raise any errors. Only if
|
||||
none work will the server give up and return an error message.
|
||||
|
||||
You can often change the text editor encoding (this depends on your
|
||||
editor though), otherwise you need to add the editor's encoding to
|
||||
Evennia's ``ENCODINGS`` list. If you are unsure, write a test file with
|
||||
lots of non-ASCII letters in the editor of your choice, then import to
|
||||
make sure it works as it should.
|
||||
|
||||
More help with encodings can be found in the entry `Text
|
||||
Encodings <TextEncodings.html>`_ and also in the Wikipedia article
|
||||
`here <http://en.wikipedia.org/wiki/Text_encodings>`_.
|
||||
|
||||
**A footnote for the batch-code processor**: Just because *Evennia* can
|
||||
parse your file and your fancy special characters, doesn't mean that
|
||||
*Python* allows their use. Python syntax only allows international
|
||||
characters inside *strings*. In all other source code only ``ASCII`` set
|
||||
characters are allowed.
|
||||
176
docs/sphinx/source/wiki/BazaarDevel.rst
Normal file
176
docs/sphinx/source/wiki/BazaarDevel.rst
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
Setting up a solo coding environment with version control
|
||||
=========================================================
|
||||
|
||||
*This page deals with working as a lone coder. See also how to use
|
||||
version control to collaborate with many people on a game
|
||||
`here <StaffVersionControl.html>`_.*
|
||||
|
||||
Version control software allows you to easily backtrack changes to your
|
||||
code, help to share your development efforts and more. Even if you are
|
||||
not contributing to Evennia itself, but is "just" developing your own
|
||||
game using Evennia, having a version control system in place is a good
|
||||
idea. If you want more info, start with the wikipedia article about it
|
||||
`here <http://en.wikipedia.org/wiki/Version_control>`_. Note that this
|
||||
page deals with commands in the Linux operating system. Details may vary
|
||||
for other systems.
|
||||
|
||||
Bazaar and SVN
|
||||
--------------
|
||||
|
||||
Evennia itself uses the *Subversion* (SVN)version control system. This
|
||||
relatively old version control system lacks some of the more modern
|
||||
features of later systems, but is universally recognized and easy to
|
||||
use. Just because we use SVN centrally does not mean that you have to
|
||||
use it when working with Evennia on your local machine however.
|
||||
|
||||
`Bazaar <http://bazaar.canonical.com>`_ (bzr) is a version control
|
||||
system written entirely in Python. It's available for all major
|
||||
platforms. It's a more modern system than SVN and is generally easy to
|
||||
use, also for newbies (other commonly seen systems similar to Bazaar are
|
||||
GIT and Mercurial). We won't go into the details of what makes Bazaar
|
||||
different from SVN, there are many texts about this on the internet.
|
||||
What is important though is that Bazaar interfaces very well with SVN,
|
||||
by use of a plugin called, *bzr-svn*.
|
||||
|
||||
Prerequisites
|
||||
-------------
|
||||
|
||||
Bazaar and bzr-svn are both available from the normal Linux package
|
||||
managers (see the homepage for how to download for other systems).
|
||||
Install those first, then give the command ``bzr`` in a terminal to make
|
||||
sure it's available.
|
||||
|
||||
First, identify to bazaar by giving the command
|
||||
``bzr whoami name <email>``
|
||||
|
||||
``bzr whoami Harry Olsson <harry@gmail.com>``
|
||||
|
||||
You can put a nickname here too if you want. This is just so the system
|
||||
knows what to put to identify new revisions.
|
||||
|
||||
Setting up for a single developer
|
||||
---------------------------------
|
||||
|
||||
We will here assume you are downloading Evennia for the first time. We
|
||||
will set up a simple environment for hacking your game in.
|
||||
|
||||
Make a new folder on your hard drive, for example named *evennia*.
|
||||
Outside this folder, give the command
|
||||
|
||||
``bzr init-repo evennia``
|
||||
|
||||
This sets the ``evennia`` folder up as a Bazaar repository, ready to
|
||||
use. Enter this folder now. Next we obtain the Evennia server, except we
|
||||
now use Bazaar to do it and not SVN.
|
||||
|
||||
``bzr checkout http://evennia.googlecode.com/svn/trunk/ evennia-trunk``
|
||||
|
||||
(Contributors use the contributor URL instead). A new folder
|
||||
``evennia-trunk`` has appeared in your repository! In it you will find
|
||||
the entire Evennia source. Working with this folder works almost
|
||||
identically to how it would work with SVN - you use ``bzr update`` to
|
||||
get the latest version, contributors use ``bzr commit`` to enter their
|
||||
changes to the server. Actually coding away in this folder is not ideal
|
||||
however. As mentioned, doing ``bzr commit`` will (attempt to) push your
|
||||
changes to the main Evennia repository, which is most often not what you
|
||||
want when developing your own game. This is where Bazaar kicks in. We
|
||||
will leave ``evennia-trunk`` be and create a separate *branch* to do our
|
||||
work in. Change your directory to the root ``evennia`` one, then copy to
|
||||
a new branch, let's call it ``evennia-mygame``:
|
||||
|
||||
``bzr branch evennia-trunk evennia-mygame``
|
||||
|
||||
A new folder appeared, containing a copy of the code. ``evennia-mygame``
|
||||
is where you do all your work. If you do commits in here, they will be
|
||||
committed locally, not to Evennia central. You now have full version
|
||||
control on your machine. Updating your work code becomes a simple
|
||||
two-step process of updating ``evennia-trunk`` and then *merging* those
|
||||
changes into ``evennia-mygame``. Read on.
|
||||
|
||||
Example work process for single developer
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
First we make sure our copy of Evennia is up-to-date. Go to
|
||||
``evennia-trunk``
|
||||
|
||||
``bzr update``
|
||||
|
||||
Bazaar goes online and gets the latest Evennia revision from the central
|
||||
repository, merging it automatically into the branch.
|
||||
|
||||
So ``evennia-trunk`` is now up-to-date. Go to ``evennia-mygame``.
|
||||
``bzr merge ../evennia-trunk``
|
||||
|
||||
The changes in ``evennia-trunk`` are pulled in and merged with
|
||||
``evennia-mygame``. You can now continue to hack away in
|
||||
``evennia-mygame``. Maybe you define new commands, fix bugs, create
|
||||
batchfiles or what have you. If you create any new files, you must tell
|
||||
Bazaar to handle them too, using the ``add`` command:
|
||||
|
||||
``bzr add <filenames>``
|
||||
|
||||
Check the current status of the version control with
|
||||
|
||||
``bzr status``
|
||||
|
||||
If you don't get any return value, you haven't made any changes since
|
||||
last commit. Otherwise you will get a list of modified files. "Unknown"
|
||||
files need to be added with ``add`` before Bazaar can track them.
|
||||
|
||||
It's usually a good idea to commit your changes often. This gives you a
|
||||
snapshot of your work that you can get back to.
|
||||
|
||||
``bzr commit``
|
||||
|
||||
This will open a text editor where you can add a message detailing your
|
||||
changes. These are the messages you see in the Evennia update list. If
|
||||
you don't want to use the editor you can set the message right away with
|
||||
the ``-m`` flag:
|
||||
|
||||
``bzr commit -m "This should fix the bug Sarah talked about."``
|
||||
|
||||
If you did changes that you wish you hadn't, you can easily get rid of
|
||||
everything since your latest commit:
|
||||
|
||||
``bzr revert``
|
||||
|
||||
You can view the full log of committed changes with
|
||||
|
||||
``bzr log``
|
||||
|
||||
See the Bazaar manuals for learning more about useful day-to-day
|
||||
commands, and special situations such as dealing with text collisions
|
||||
etc.
|
||||
|
||||
Evennia Contributor
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If you are an Evennia contributor, you can also have use of the Bazaar
|
||||
setup above. The only difference is that you then also have commit
|
||||
permission to the Evennia main repository.
|
||||
|
||||
You can have any number of work branches in your ``evennia`` folder.
|
||||
Let's say your work branch for fixing Evennia bugs and features is
|
||||
``evennia-work``. You update and work with this the same way as
|
||||
``evennia-mygame`` above.
|
||||
|
||||
After having committed your latest changes, move to the
|
||||
``evennia-trunk`` folder.
|
||||
|
||||
``bzr update``
|
||||
|
||||
This makes sure your local trunk is up-to-date.
|
||||
|
||||
``bzr merge ../evennia-work``
|
||||
|
||||
This merges your updates into the ``evennia-trunk`` branch.
|
||||
|
||||
``bzr commit``
|
||||
|
||||
Give the commit message and your changes will be pushed to the central
|
||||
repository. Done!
|
||||
|
||||
.. figure:: http://d.imagehost.org/0452/bazaar_repo1.png
|
||||
:align: center
|
||||
:alt:
|
||||
|
||||
27
docs/sphinx/source/wiki/BuilderDocs.rst
Normal file
27
docs/sphinx/source/wiki/BuilderDocs.rst
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
Builder Documentation
|
||||
=====================
|
||||
|
||||
This section contains information useful to world builders.
|
||||
|
||||
Building basics
|
||||
---------------
|
||||
|
||||
- `Default in-game commands <DefaultCommandHelp.html>`_
|
||||
- `Building Quick-start <BuildingQuickstart.html>`_
|
||||
- `Giving build permissions to others <BuildingPermissions.html>`_
|
||||
- `Adding colour <Colours.html>`_
|
||||
- `Customizing the connection screen <ConnectionScreen.html>`_
|
||||
|
||||
World creation
|
||||
--------------
|
||||
|
||||
`Overview of batch processors <BatchProcessors.html>`_
|
||||
|
||||
- `Batch-command processor <BatchCommandProcessor.html>`_
|
||||
- `Batch-code processor <BatchCodeProcessor.html>`_
|
||||
|
||||
The Tutorial world
|
||||
------------------
|
||||
|
||||
- `Introduction and setup <TutorialWorldIntroduction.html>`_
|
||||
|
||||
54
docs/sphinx/source/wiki/BuildingPermissions.rst
Normal file
54
docs/sphinx/source/wiki/BuildingPermissions.rst
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
Giving permissions to your staff
|
||||
================================
|
||||
|
||||
*OBS: This gives only a brief introduction to the access system. Locks
|
||||
and permissions are fully detailed `here <Locks.html>`_.*
|
||||
|
||||
The super user
|
||||
--------------
|
||||
|
||||
There are strictly speaking two types of users in Evennia, the *super
|
||||
user* and everyone else. The superuser is the first user you create,
|
||||
object #1. This is the all-powerful server-owner account. A superuser
|
||||
account has access to everything and no locks affect them. Technically
|
||||
the superuser not only has all access, it even bypasses the permission
|
||||
checks entirely. This makes the superuser impossible to lock out, but
|
||||
makes it unsuitable to actually play-test the game's locks and
|
||||
restrictions with. Usually there is no need to have but one superuser.
|
||||
|
||||
Assigning permissions
|
||||
---------------------
|
||||
|
||||
Whereas permissions can be used for anything, those put in
|
||||
settings.PERMISSION\_HIERARCHY will have a ranking relative each other
|
||||
as well. By default Evennia creates the following hierarchy:
|
||||
|
||||
#. *Immortals* - these basically have all the same access as superusers
|
||||
(except that they do not sidestep the Permission system). Assign only
|
||||
to really trusted server-admin staff.
|
||||
#. *Wizards* can do everything except affecting the server functions
|
||||
itself. So a wizard couldn't reload or shutdown the server for
|
||||
example. They also cannot execute arbitrary Python code on the
|
||||
console or import files from the hard drive.
|
||||
#. *Builders* has all the build commands, but cannot affect other
|
||||
players or mess with the server.
|
||||
#. *!PlayerHelpers* are almost like a normal *Player*, but they can also
|
||||
add help files to the database.
|
||||
#. *Players* is the default group that new players end up in. A new
|
||||
player have permission to use tells, to use and create new channels.
|
||||
|
||||
A user having a higher-level permission also automatically have access
|
||||
to locks requiring only lower-level access.
|
||||
|
||||
To assign a new permission from inside the game, you need to be able to
|
||||
use the ``@perm`` command. This is an *Immortal*-level command, but it
|
||||
could in principle be made lower-access since it only allows assignments
|
||||
equal or lower to your current level (so you cannot use it to escalate
|
||||
your own permission level). So, assuming you yourself have *Immortal*
|
||||
access (or is superuser), you assign a new player "Tommy" to your core
|
||||
staff with the command
|
||||
|
||||
::
|
||||
|
||||
@perm/add Tommy = Immortals
|
||||
|
||||
301
docs/sphinx/source/wiki/BuildingQuickstart.rst
Normal file
301
docs/sphinx/source/wiki/BuildingQuickstart.rst
Normal file
|
|
@ -0,0 +1,301 @@
|
|||
A quick-start guide to in-game building in Evennia.
|
||||
|
||||
Building Quick-start
|
||||
====================
|
||||
|
||||
The default `command <Commands.html>`_ definitions coming with Evennia
|
||||
follows a style `similar <UsingMUXAsAStandard.html>`_ to that of MUX, so
|
||||
the commands should be familiar if you used any such code bases before.
|
||||
If you haven't, you might be confused by the use of ``@`` all over. This
|
||||
is just a naming convention - commands related to out-of-character or
|
||||
admin-related actions tend to start with ``@``, the symbol has no
|
||||
meaning of its own.
|
||||
|
||||
The default commands have the following style (where ``[...]`` marks
|
||||
optional parts):
|
||||
|
||||
::
|
||||
|
||||
command[/switch/switch...] [arguments ...]
|
||||
|
||||
A *switch* is a special, optional flag to the command to make it behave
|
||||
differently. It is always put directly after the command name, and
|
||||
begins with a forward slash (``/``). The *arguments* are one or more
|
||||
inputs to the commands. It's common to use an equal sign (``=``) when
|
||||
assigning something to an object.
|
||||
|
||||
Below are some examples of commands. Use ``help <command>`` for learning
|
||||
more about each command and their detailed options.
|
||||
|
||||
Creating an object
|
||||
------------------
|
||||
|
||||
Basic objects can be anything -- swords, flowers and non-player
|
||||
characters. They are created using the ``@create`` command:
|
||||
|
||||
::
|
||||
|
||||
> @create box
|
||||
|
||||
This created a new 'box' (of the default object type) in your inventory.
|
||||
Use the command ``inventory`` (or ``i``) to see it. Now, 'box' is a
|
||||
rather short name, let's is give a few aliases.
|
||||
|
||||
::
|
||||
|
||||
> @name box = very large box;box;very;bo;crate
|
||||
|
||||
We now actually renamed the box to *very large box* (and this is what we
|
||||
will see when looking at the room), but we will also recognize it by any
|
||||
of the other names we give - like *crate* or simply *box* as before. We
|
||||
could have given these aliases directly after the name in the
|
||||
``@create`` command, this is true for all creation commands - you can
|
||||
always tag on a list of ;-separated aliases to the name of your new
|
||||
object. If you had wanted to not change the name itself, but to only add
|
||||
aliases, you could have used the ``@alias`` command.
|
||||
|
||||
We are currently carrying the box, which you can see if you give the
|
||||
command ``inventory`` (or ``i``). Let's drop it.
|
||||
|
||||
::
|
||||
|
||||
> drop box
|
||||
|
||||
Hey presto - there it is on the ground, in all its normality (you can
|
||||
also create & drop in one go using the ``/drop`` switch, like this:
|
||||
``@create/drop box``).
|
||||
|
||||
::
|
||||
|
||||
> examine box
|
||||
|
||||
This will show some technical details about the box object (you can
|
||||
normally just write ``ex`` as a short for ``examine``).
|
||||
|
||||
Try to ``look`` at the box to see the (default) description.
|
||||
|
||||
::
|
||||
|
||||
> look box
|
||||
|
||||
Let's add some flavor.
|
||||
|
||||
::
|
||||
|
||||
> @describe box = This is a large and very heavy box.
|
||||
|
||||
If you try the ``get`` command we will pick up the box. So far so good,
|
||||
but if we really want this to be a large and heavy box, people should
|
||||
*not* be able to run off with it that easily. To prevent this we need to
|
||||
lock it down. This is done by assigning a *Lock* to it. Make sure the
|
||||
box was dropped in the room, then try this:
|
||||
|
||||
::
|
||||
|
||||
> @lock box = get:false()
|
||||
|
||||
Locks are a rather `big topic <Locks.html>`_, but for now that will do
|
||||
what we want. This will lock the box so noone can lift it (except
|
||||
superusers, they override all locks and pick it up anyway). Make sure
|
||||
you log in as another user than #1 and try to get the box now:
|
||||
|
||||
::
|
||||
|
||||
> get box You can't get that.
|
||||
|
||||
Think the default error message looks dull? The ``get`` command looks
|
||||
for an `Attribute <Attributes.html>`_ named ``get_err_msg`` for
|
||||
returning a nicer error message (we just happen to know this, you would
|
||||
currently need to peek into the code for the ``get`` command to find
|
||||
out. You set attributes using the ``@set`` command (if you logged in as
|
||||
another user, you need to have build permissions again for this):
|
||||
|
||||
::
|
||||
|
||||
> @set box/get_err_msg = The box is way too heavy for you to lift.
|
||||
|
||||
Try to get it now and you should see a nicer error message echoed back
|
||||
to you.
|
||||
|
||||
Get a personality
|
||||
-----------------
|
||||
|
||||
`Scripts <Scripts.html>`_ are powerful things that allows time-dependent
|
||||
effects on objects. To try out a first script, let's put one on
|
||||
ourselves. There is an example script in
|
||||
``game/gamesrc/scripts/examples/bodyfunctions.py`` that is called
|
||||
``BodyFunctions``. To add this to us we will use the ``@script``
|
||||
command:
|
||||
|
||||
::
|
||||
|
||||
> @script self = examples.bodyfunctions.BodyFunctions
|
||||
|
||||
(note that you don't have to give the full path as long as you are
|
||||
pointing to a place inside the ``gamesrc/scripts`` directory). Wait a
|
||||
while and you will notice yourself starting making random observations.
|
||||
|
||||
::
|
||||
|
||||
> examine self
|
||||
|
||||
This will show details about yourself. You will also see the script and
|
||||
how long it is until it "fires" next (a randomizer determines if it will
|
||||
say something, so you will not see any output every time it fires).
|
||||
|
||||
When you are tired of this, kill the script with
|
||||
|
||||
::
|
||||
|
||||
> @script/stop self = examples.bodyfunctions.BodyFunctions
|
||||
|
||||
Pushing your buttons
|
||||
--------------------
|
||||
|
||||
If we get back to the box we made, there is only so much fun you can do
|
||||
with it at this point. It's just a dumb generic object. If you renamed
|
||||
it ``carpet`` and changed its description noone would be the wiser.
|
||||
However, with the combined use of custom
|
||||
`Typeclasses <Typeclasses.html>`_, `Scripts <Scripts.html>`_ and
|
||||
object-based `Commands <Commands.html>`_, you could expand it and other
|
||||
items to be as unique, complex and interactive as you want.
|
||||
|
||||
Let's take an example. So far we have only created objects that use the
|
||||
default object typeclass found in
|
||||
``game/gamesrc/objects/baseobjects.py``. It is called simply *Object*.
|
||||
Let's create an object that is a little more interesting. Under
|
||||
``game/gamesrc/objects/`` there is a directory ``examples`` with a
|
||||
module ``red_button.py``. It contains the enigmatic *!RedButton*
|
||||
typeclass.
|
||||
|
||||
Let's make us one of *those*!
|
||||
|
||||
::
|
||||
|
||||
> @create/drop button:examples.red_button.RedButton
|
||||
|
||||
With the ``/drop`` switch we make sure to drop the button right away
|
||||
without having to use the ``drop`` command later. We import the
|
||||
*!RedButton* python class the same way you would import it in Python
|
||||
except Evennia defaults to looking in ``game/gamesrc/objects/`` so you
|
||||
don't have to write the full path every time. There you go - one red
|
||||
button.
|
||||
|
||||
The *!RedButton* is an example object intended to show off many of
|
||||
Evennia's features. You will find that the `Scripts <Scripts.html>`_ and
|
||||
`Commands <Commands.html>`_ controlling it are scattered in
|
||||
``examples``-folders all across ``game/gamesrc/``.
|
||||
|
||||
If you wait for a while (make sure you dropped it!) the button will
|
||||
blink invitingly. Why don't you try to push it ...? Surely a big red
|
||||
button is meant to be pushed. You know you want to.
|
||||
|
||||
Creating a room called 'house'
|
||||
------------------------------
|
||||
|
||||
The main command for shaping the game world is ``@dig``. If you for
|
||||
example are standing in Limbo, you can in one go dig a route 'north' to
|
||||
your new house location like this:
|
||||
|
||||
::
|
||||
|
||||
> @dig house = large red door;door;in, to the outside;out
|
||||
|
||||
This will create a new room named 'house'. It will also directly create
|
||||
an exit from your current location named 'large red door' and a
|
||||
corresponding exit named 'to the outside' in the house room leading back
|
||||
to Limbo. We also define a few aliases to those exits, so people don't
|
||||
have to write the full thing all the time.
|
||||
|
||||
If you wanted to use normal compass directions (north, west, southwest
|
||||
etc), you could do that with ``@dig`` too. But Evennia also has a
|
||||
limited version of ``@dig`` that helps for compass directions (and also
|
||||
up/down and in/out). It's called ``@tunnel``:
|
||||
|
||||
::
|
||||
|
||||
> @tunnel sw = cliff
|
||||
|
||||
This will create a new room "cliff" with an exit "southwest" leading
|
||||
there and a path "northeast" leading back from the cliff to your current
|
||||
location.
|
||||
|
||||
You can create exits from anywhere at any time using the ``@open``
|
||||
command:
|
||||
|
||||
::
|
||||
|
||||
> @open north;n = house
|
||||
|
||||
This opens an exit ``north`` to the previously created room ``house``.
|
||||
|
||||
If you have many rooms named ``house`` you will get a list of matches
|
||||
and have to select which one you want to link to. You can also give its
|
||||
database ref number, which is unique to every object. This can be found
|
||||
with the ``examine`` command or by looking at the latest constructions
|
||||
with ``@objects``.
|
||||
|
||||
Follow the north exit to your 'house' or ``@teleport`` to it:
|
||||
|
||||
::
|
||||
|
||||
> north
|
||||
|
||||
or:
|
||||
|
||||
::
|
||||
|
||||
> @teleport house
|
||||
|
||||
To manually open an exit back to Limbo (if you didn't do so with the
|
||||
``@dig`` command):
|
||||
|
||||
::
|
||||
|
||||
> @open door = limbo
|
||||
|
||||
(or give limbo's dbref which is #2)
|
||||
|
||||
Finding and manipulating existing objects
|
||||
-----------------------------------------
|
||||
|
||||
To re-point an exit at another room or object, you can use
|
||||
|
||||
::
|
||||
|
||||
> @link <room name> = <new_target name>
|
||||
|
||||
To find something, use
|
||||
|
||||
::
|
||||
|
||||
> @find <name>
|
||||
|
||||
This will return a list of dbrefs that have a similar name.
|
||||
|
||||
To teleport something somewhere, one uses
|
||||
|
||||
::
|
||||
|
||||
> @teleport <object> = <destination>
|
||||
|
||||
To destroy something existing, use
|
||||
|
||||
::
|
||||
|
||||
> @destroy <object>
|
||||
|
||||
You can destroy many objects in one go by giving a comma-separated list
|
||||
of objects to the command.
|
||||
|
||||
Adding a help entry
|
||||
-------------------
|
||||
|
||||
An important part of building is keeping the help files updated. You can
|
||||
add, delete and append to existing help entries using the ``@sethelp``
|
||||
command.
|
||||
|
||||
::
|
||||
|
||||
> @sethelp/add MyTopic = This help topic is about ...
|
||||
|
||||
60
docs/sphinx/source/wiki/ChoosingAnSQLServer.rst
Normal file
60
docs/sphinx/source/wiki/ChoosingAnSQLServer.rst
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
Choosing an SQL Server
|
||||
======================
|
||||
|
||||
Since Evennia uses `Django <http://djangoproject.com>`_, most of our
|
||||
notes are based off of what we know from the community and their
|
||||
documentation. While the information below may be useful, you can always
|
||||
find the most up-to-date and "correct" information at Django's `Notes
|
||||
about supported
|
||||
Databases <http://docs.djangoproject.com/en/dev/ref/databases/#ref-databases>`_
|
||||
page.
|
||||
|
||||
SQLite
|
||||
------
|
||||
|
||||
This is the default database used, and for the vast majority of sites
|
||||
out there, will probably be more than adequate. No server process is
|
||||
needed, the administrative overhead is tiny (as is resource
|
||||
consumption). The database will appear as a simple file
|
||||
(``game/evennia.db`` by default). Purging your database is just a matter
|
||||
of deleting this file and re-running the database creation commands in
|
||||
GettingStarted.
|
||||
|
||||
It is not tested how well Evennia performs with SQLite under a heavier
|
||||
load, but it should probably be fine given the relative simplicity of
|
||||
our applications.
|
||||
|
||||
**Note:** If you run Windows and for some reason need to use a
|
||||
third-party web server like Apache rather than Evennia's internal web
|
||||
server, sqlite is probably not be the best choice. This is due to the
|
||||
possibility of clashes with file-locking of the database file under
|
||||
Windows.
|
||||
|
||||
Postgres
|
||||
--------
|
||||
|
||||
This is Django's recommended DB engine, and the one that we recommend
|
||||
for all sites aspiring to grow to a larger size. While not as fast as
|
||||
SQLite for simple purposes, it will scale infinitely better than SQLite,
|
||||
especially if your game has an extensive web presence.
|
||||
|
||||
MySQL
|
||||
-----
|
||||
|
||||
While perfectly reasonable to deploy under, the MySQL driver for Django
|
||||
has some very slight oddities (at the time of this document's writing)
|
||||
that probably don't affect our usage case that much (if at all). Make
|
||||
sure you look at the aforementioned `Notes about supported
|
||||
Databases <http://docs.djangoproject.com/en/dev/ref/databases/#ref-databases>`_
|
||||
page for the latest on this.
|
||||
|
||||
MySQL **may** be slightly faster than Postgres depending on your setup
|
||||
and software versions involved.
|
||||
|
||||
Others
|
||||
------
|
||||
|
||||
No testing has been performed with Oracle, but it is also supported.
|
||||
There are community maintained drivers for `MS
|
||||
SQL <http://code.google.com/p/django-mssql/>`_ and possibly a few others
|
||||
(found via our friend, Google).
|
||||
59
docs/sphinx/source/wiki/Colours.rst
Normal file
59
docs/sphinx/source/wiki/Colours.rst
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
Putting Colour to your game
|
||||
===========================
|
||||
|
||||
<wiki:comment> </wiki:comment>
|
||||
|
||||
*Note that the Wiki does not display colour the way it would look on the
|
||||
screen.*
|
||||
|
||||
Evennia supports the ``ANSI`` standard for displaying text. This means
|
||||
that you can put markers in your text and if the user's
|
||||
client/console/display supports those markers, they will see the text in
|
||||
the specified colour. Remember that whereas there is, for example, one
|
||||
special marker meaning "yellow", which colour (hue) of yellow is
|
||||
*actually* displayed on the user's screen depends on the settings of
|
||||
their particular mud client/viewer. They could even swap around the
|
||||
colours displayed if they wanted to. or turn them off altogether. Some
|
||||
clients don't support colour from the onset - text games are also played
|
||||
with special reading equipment by people who are blind or have otherwise
|
||||
diminished eyesight. So a good rule of thumb is to use colour to enhance
|
||||
your game, but don't *rely* on it to display critical information. If
|
||||
you are coding the game, you can add functionality to let users disable
|
||||
colours as they please, as described `here <RemovingColour.html>`_.
|
||||
|
||||
Adding colour to in-game text is easy. You just put in special markers
|
||||
in your text that tell Evennia when a certain colour begins and when it
|
||||
ends. There are two markup styles. The traditional(?) one use ``%c#`` to
|
||||
mark colour:
|
||||
|
||||
::
|
||||
|
||||
This is a %crRed text%cn This is normal text again. %cRThis text has red background%cn this is normal text.
|
||||
|
||||
``%c#`` - markup works like a switch that is on until you actively turn
|
||||
it off with ``%cn`` (this returns the text to your default setting).
|
||||
Capital letters mean background colour, lower-case means letter-colour.
|
||||
So ``%cR`` means a red area behind your normal-colour text. If you
|
||||
combine red background with red foreground text - ``%cR%cr``, you get a
|
||||
solid red block with no characters visible! Similarly, ``%cR%cx`` gives
|
||||
red background with black text. ``%ch`` 'hilights' your current text, so
|
||||
grey becomes white, dark yellow becomes bright yellow etc.
|
||||
|
||||
The drawback of the ``%cs`` style has to do with how Python formats
|
||||
strings - the ``%`` is used in Python to create special text formatting,
|
||||
and combining that with colour codes easily leads to messy and
|
||||
unreadable code. It is thus often easier to use ``#`` style codes:
|
||||
|
||||
::
|
||||
|
||||
This is a rBright red textn This is normal text again
|
||||
|
||||
The ``x`` format don't include background colour, it only colours the
|
||||
foreground text. The basic rule is that lower-case letter means bright
|
||||
(hilighted) colour, whereas the upper-case one is for darker colour. So
|
||||
``g`` means bright green and ``G`` means dark green. ``n`` returns to
|
||||
normal text colour. The equivalent in ``%c``-style markup is ``%cg%ch``
|
||||
for bright green and ``%cg`` for dark green.
|
||||
|
||||
You can find a list of all the parsed ``ANSI``-colour codes in
|
||||
``src/utils/ansi.py``.
|
||||
85
docs/sphinx/source/wiki/CommandPrompt.rst
Normal file
85
docs/sphinx/source/wiki/CommandPrompt.rst
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
Adding a command prompt
|
||||
=======================
|
||||
|
||||
A *prompt* is quite common in MUDs. The prompt display useful details
|
||||
about your character that you are likely to want to keep tabs on at all
|
||||
times, such as health, magical power etc. It might also show things like
|
||||
in-game time, weather and so on.
|
||||
|
||||
Prompt after the command
|
||||
------------------------
|
||||
|
||||
The easiest form of prompt is one that is sent after every command you
|
||||
send. So, say you enter the look command; you would then get the result
|
||||
of the look command, followed by the prompt. As an example:
|
||||
|
||||
::
|
||||
|
||||
> look You see nothing special. HP:10, SP:20, MP: 5
|
||||
|
||||
MUD clients can be set to detect prompts like this and display them in
|
||||
various client-specific ways.
|
||||
|
||||
To add this kind of "after-every-command-prompt", you can use the
|
||||
``at_post_cmd()`` hook. This is to be defined on the Command class and
|
||||
Evennia will always call it right after ``func()`` has finished
|
||||
executing. For this to appear after every command you enter, it's best
|
||||
to put this in the parent for your commands (for the default commands
|
||||
this would be ``MuxCommand``), but you could also put it only in certain
|
||||
commands (might not be too useful to show it if you are doing game
|
||||
administration for example).
|
||||
|
||||
::
|
||||
|
||||
class MyCommand(Command): [...] def at_post_cmd(self): # we assume health/stamina/magic are just stored # as simple attributes on the character. hp = self.caller.db.hp sp = self.caller.db.sp mp = self.caller.db.mp self.caller.msg("HP: %i, SP: %i, MP: %i" % (hp, sp, mp))
|
||||
|
||||
Prompt on the same line
|
||||
-----------------------
|
||||
|
||||
Another, more advanced type of prompt is one that appears before the
|
||||
return of every command, on the same line:
|
||||
|
||||
::
|
||||
|
||||
> look HP: 10, SP:20, MP:5 -- You see nothing special.
|
||||
|
||||
Now, there is an ``at_pre_cmd()`` hook analogous to the hook from last
|
||||
section except called just *before* parsing of the command. But putting
|
||||
prompt code in that would just have the prompt appear on the *line
|
||||
before* the function return:
|
||||
|
||||
::
|
||||
|
||||
> look HP:10, SP:20, MP: 5 You see nothing special.
|
||||
|
||||
... which might be cool too, but not what we wanted. To have the prompt
|
||||
appear on the same line as the return this, we need to change how
|
||||
messages are returned to the player. This means a slight modification to
|
||||
our *Character class* (see `here <Objects#Characters.html>`_ on how to
|
||||
change the default Character class to your custom one). Now, all
|
||||
commands use the ``object.msg()`` method for communicating with the
|
||||
player. This is defined in ``src/objects/models.py``, on the
|
||||
``ObjectDB`` base class. This is how the ``msg()`` method is defined:
|
||||
|
||||
::
|
||||
|
||||
def msg(self, outgoing_message, from_obj=None, data=None): ...
|
||||
|
||||
The only argument we are interested in here is the ``outgoing_message``,
|
||||
which contains the text that is about to be passed on to the player. We
|
||||
want to make sure that ``msg()`` always tack our prompt in front of the
|
||||
``outgoing_message`` before sending it on. This is done by simply
|
||||
overloading the ``msg()`` method in our custom Character class. On your
|
||||
custom Character typeclass add this:
|
||||
|
||||
::
|
||||
|
||||
def msg(self, outgoing_message, from_obj=None, data=None): # prepend the prompt in front of the message hp = self.db.hp sp = self.db.sp mp = self.db.mp prompt = "%i, %i, %i -- " % (hp, sp, mp) outgoing_message = prompt + outgoing_message # pass this on to the original msg() method on the database object self.dbobj.msg(outgoing_message, from_obj=from_obj, data=data)
|
||||
|
||||
Note that this solution will *always* give you the prompt, also if you
|
||||
use admin commands, which could get annoying. You might want to have
|
||||
some attribute defined on your character for turning on/off the prompt
|
||||
(the msg() method could look for it to determine if it should add the
|
||||
prompt or not). You can of course also name the above method
|
||||
``msg_prompt()`` and make sure that only commands that *should* return a
|
||||
prompt call this version.
|
||||
608
docs/sphinx/source/wiki/Commands.rst
Normal file
608
docs/sphinx/source/wiki/Commands.rst
Normal file
|
|
@ -0,0 +1,608 @@
|
|||
Details on how to use and extend the command system.
|
||||
|
||||
Command system
|
||||
==============
|
||||
|
||||
The basic way for users to communicate with the game is through
|
||||
*Commands*. These can be commands directly related to the game world
|
||||
such as *look*, *get*, *drop* and so on, or administrative commands such
|
||||
as *examine* or *@dig*.
|
||||
|
||||
The `default commands <DefaultCommandHelp.html>`_ coming with Evennia
|
||||
are 'MUX-like' in that they use @ for admin commands, support things
|
||||
like switches, syntax with the '=' symbol etc, but there is nothing that
|
||||
prevents you from implementing a completely different command scheme for
|
||||
your game. You can find the default commands in
|
||||
``src/commands/default``. You should not edit these directly - they will
|
||||
be updated by the Evennia team as new features are added. Rather you
|
||||
should look to them for inspiration and inherit your own designs from
|
||||
them.
|
||||
|
||||
There are two components to having a command running - the *Command*
|
||||
class and the *Command Set* you want to store that command in.
|
||||
|
||||
A *Command* is a python class containing all the functioning code for
|
||||
what a command does - for example, a *look* command would contain code
|
||||
for describing other objects.
|
||||
|
||||
A *Command Set* (often referred to as a !CmdSet) is a python class
|
||||
holding any number of Command class instances, and one Command can go
|
||||
into many different command sets. By storing the command set on a
|
||||
character object you will make all the commands therein available to use
|
||||
by that character. You can also store command sets on normal objects if
|
||||
you want users to be able to use the object in various ways. Consider a
|
||||
"Tree" object with a cmdset defining the commands *climb* and *shop
|
||||
down*. Or a "Clock" with a cmdset containing the single command *check
|
||||
time*.
|
||||
|
||||
Defining a Command
|
||||
------------------
|
||||
|
||||
All commands are implemented as normal Python classes inheriting from
|
||||
the base class ``Command``
|
||||
(``game.gamesrc.commands.basecommand.Command``). You will find that this
|
||||
base class is very "bare". The default commands of Evennia actually
|
||||
inherit from a child of ``Command`` called ``MuxCommand`` - this is the
|
||||
class that knows all the mux-like syntax like ``/switches``, splitting
|
||||
by "=" etc. Below we'll avoid mux-specifics and use the base ``Command``
|
||||
class directly.
|
||||
|
||||
You define a new command by assigning a few class-global properties on
|
||||
your inherited class and overloading one or two hook functions. The full
|
||||
gritty mechanic behind how commands work are found towards the end of
|
||||
this page; for now you only need to know that the command handler
|
||||
creates an instance of this class when you call that command, then
|
||||
assigns the new object a few useful properties that you can assume to
|
||||
always be available.
|
||||
|
||||
Properties assigned to the command instance at run-time
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Let's say player *Bob* with a character *!BigGuy* enters the command
|
||||
``look at sword``. After the system having successfully identified this
|
||||
a the "look" command and determined that *!BigGuy* really has access to
|
||||
a command named ``look``, it chugs the ``look`` command class out of
|
||||
storage and creates a new instance of it. After some more checks it then
|
||||
assigns it the following properties:
|
||||
|
||||
- ``caller`` - a reference to the object executing the command - this
|
||||
is normally *!BigGuy*, not *Bob*! The command system usually deals
|
||||
with things on the character level. If you want to do something to
|
||||
the player in your command, do so through ``caller.player``. The only
|
||||
exception to this is if you stored your cmdset directly on the
|
||||
*Player* object (usually used only when a Player has no character
|
||||
assigned to them, like when creating a new one).
|
||||
- ``cmdstring`` - the matched key for the command. This would be
|
||||
"``look``" in our example.
|
||||
- ``args`` - this is the rest of the string, except the command name.
|
||||
So if the string entered was ``look at sword``, ``args`` would simply
|
||||
be "``at sword``".
|
||||
- ``obj`` - the game `Object <Objects.html>`_ on which this command is
|
||||
defined. This need not be the caller, but since ``look`` is a common
|
||||
(default) command, this is probably defined directly on *!BigGuy* -
|
||||
so ``obj`` will point to !BigGuy. Otherwise ``obj`` could be any
|
||||
interactive object with commands defined on it, like in the example
|
||||
of the "check time" command defined on a "Clock" object or a `red
|
||||
button <https://code.google.com/p/evennia/source/browse/trunk/game/gamesrc/objects/examples/red%3Ci%3Ebutton.py.html>`_
|
||||
that you can "``push``".
|
||||
- ``cmdset`` - this is a reference to the merged CmdSet (see below)
|
||||
from which this command was matched. This variable is rarely used,
|
||||
it's main use is for the `auto-help system <HelpSystem.html>`_
|
||||
(Advanced note: the merged cmdset need NOT be the same as
|
||||
!BigGuy.cmdset. The merged set can be a combination of the cmdsets
|
||||
from other objects in the room, for example\_).
|
||||
|
||||
Defining your own command classes
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Beyond the properties Evennia always assigns to the command at runtime
|
||||
(listed above), your job is to define the following class properties:
|
||||
|
||||
- ``key`` - the identifier for the command, like ``look``. This should
|
||||
(ideally) be unique. it can be more than one word long in a string,
|
||||
like "press button". Maximum number of space-separated words that can
|
||||
be part of a command name is given by ``settings.CMD_MAXLEN``.
|
||||
- ``aliases`` (optional) - a list of alternate names for the command
|
||||
(``["l", "glance", "see"]``). Same name rules as for ``key`` applies.
|
||||
- ``locks`` - a `lock definition <Locks.html>`_, usually on the form
|
||||
``cmd:<lockfuncs>``. Locks is a rather big topic, so until you learn
|
||||
more about locks, stick to giving the lockstring ``"cmd:all()"`` to
|
||||
make the command available to everyone.
|
||||
- ``help_category`` (optional) - setting this helps to structure the
|
||||
auto-help into categories. If none is set, this will be set to
|
||||
*General*.
|
||||
|
||||
You should also implement at least two methods, ``parse()`` and
|
||||
``func()`` (You could also implement ``perm()``, but that's not needed
|
||||
unless you want to fundamentally change how access checks work).
|
||||
|
||||
``parse()`` is intended to parse the arguments (``self.args``) of the
|
||||
function. You can do this in any way you like, then store the result(s)
|
||||
in variable(s) on the command object itself (i.e. on ``self``). The
|
||||
default mux-like system uses this method to detect "command switches",
|
||||
to take one example.
|
||||
|
||||
``func()`` is called right after ``parse()`` and should make use of the
|
||||
pre-parsed input to actually do whatever the command is supposed to do.
|
||||
This is the main body of the command.
|
||||
|
||||
Finally, you should always make an informative ```__doc__``
|
||||
string <http://www.python.org/dev/peps/pep-0257/#what-is-a-docstring>`_
|
||||
at the top of your class. This string is dynamically read by the `Help
|
||||
system <HelpSystem.html>`_ to create the help entry for this command.
|
||||
You should decide on a way to format your help and stick to that.
|
||||
|
||||
Below is how you define a simple alternative "``look at``" command:
|
||||
|
||||
::
|
||||
|
||||
from game.gamesrc.commands.basecommand import Commandclass CmdLookAt(Command): """ An alternative (and silly) look command Usage: look at <what> Where <what> may only be 'here' in this example. This initial string (the __doc__ string) is also used to auto-generate the help for this command ... """ key = "look at" # this is the command name to use aliases = ["la", "look a"] # aliases to the command name locks = "cmd:all()" help_category = "General" def parse(self): "Very trivial parser" self.what = self.args.strip() def func(self): "This actually does things" caller = self.caller if not self.what: caller.msg("Look at what?") elif self.what == 'here': # look at the current location description = caller.location.db.desc caller.msg(description) else: # we don't add any more functionality in this example caller.msg("Sorry, you can only look 'here'...")
|
||||
|
||||
The power of having commands as classes and to separate ``parse()`` and
|
||||
``func()`` lies in the ability to inherit functionality without having
|
||||
to parse every command individually. For example, as mentioned the
|
||||
default commands all inherit from ``MuxCommand``. ``MuxCommand``
|
||||
implements its own version of ``parse()`` that understands all the
|
||||
specifics of MUX-like commands. Almost none of the default commands thus
|
||||
need to implement ``parse()`` at all, but can assume the incoming string
|
||||
is already split up and parsed in suitable ways by its parent.
|
||||
|
||||
So we have created our own first command! But Evennia doesn't know about
|
||||
it yet. To tell it we have to add it to a *Command Set*.
|
||||
|
||||
Command Sets
|
||||
------------
|
||||
|
||||
All commands in Evennia are always grouped together into *Command Sets*
|
||||
(!CmdSets). A particular ``Command`` class definition can be part of any
|
||||
number of different !CmdSets. CmdSets can be stored on game
|
||||
`objects <Objects.html>`_ and on `Players <Players.html>`_ respectively.
|
||||
|
||||
When a user issues a command, it is matched against the contents of all
|
||||
cmdsets available at the time, `merged
|
||||
together <Commands#Adding%3Ci%3Eand%3C/i%3Emerging%3Ci%3Ecommand%3C/i%3Esets.html>`_.
|
||||
The currently valid command sets are collected from the following
|
||||
sources, in this order:
|
||||
|
||||
- The active cmdset on the character object
|
||||
- The cmdsets of objects carried by the character
|
||||
- The cmdset of the current location
|
||||
- The cmdset of objects in the currrent location (this includes exits)
|
||||
- The channel commandset
|
||||
- The cmdset defined on the Player object controlling the character
|
||||
(OOC cmdset)
|
||||
|
||||
The default ``CmdSet`` shipping with Evennia is automatically added to
|
||||
all new characters and contains commands such as ``look``, ``drop``,
|
||||
``@dig`` etc. You can find it defined in
|
||||
``src/commands/default/cmdset_default.py``, but it is also referenced by
|
||||
``game/gamesrc/commands/basecmdset.py``. Players have an
|
||||
Out-of-character cmdset called ``cmdset_ooc`` that can also be found
|
||||
from the same place. There is finally an "unloggedin" cmdset that is
|
||||
used before the Player has authenticated to the game. The path to these
|
||||
three standard command sets are defined in settings, as
|
||||
``CMDSET_UNLOGGEDIN``, ``CMDSET_DEFAULT`` and ``CMDSET_OOC``. You can
|
||||
create any number of command sets besides those to fit your needs.
|
||||
|
||||
A CmdSet is, as most things in Evennia, defined as a Python class
|
||||
inheriting from the correct parent (``src.commands.cmdset.CmdSet``). The
|
||||
CmdSet class only needs to define one method, called
|
||||
``at_cmdset_creation()``. All other class parameters are optional, but
|
||||
are used for more advanced set manipulation and coding (see the `merge
|
||||
rules <Commands#Merge_rules.html>`_ section).
|
||||
|
||||
::
|
||||
|
||||
from src.commands.cmdset import CmdSet from game.gamesrc.commands import mycommandsclass MyCmdSet(CmdSet): def at_cmdset_creation(self): """ The only thing this method should need to do is to add commands to the set. """ self.add(mycommands.MyCommand1()) self.add(mycommands.MyCommand2()) self.add(mycommands.MyCommand3())
|
||||
|
||||
The !CmdSet's ``add()`` method can also take another CmdSet as input. In
|
||||
this case all the commands from that CmdSet will be appended to this one
|
||||
as if you added them line by line:
|
||||
|
||||
::
|
||||
|
||||
at_cmdset_creation(): ... self.add(AdditionalCmdSet) # adds all command from this set ...
|
||||
|
||||
If you added your command to an existing cmdset (like to the default
|
||||
cmdset), that set is already loaded into memory. You need to make the
|
||||
server aware of the code changes:
|
||||
|
||||
::
|
||||
|
||||
@reload
|
||||
|
||||
You should now be able to use the command.
|
||||
|
||||
If you created a new, fresh cmdset, this must be added to an object in
|
||||
order to make the commands within available. A simple way to temporarily
|
||||
test a cmdset on yourself is use the ``@py`` command to execute a python
|
||||
snippet:
|
||||
|
||||
::
|
||||
|
||||
@py self.cmdset.add('game.gamesrc.commands.mycmdset.MyCmdSet')
|
||||
|
||||
This will stay with you until you shut down the server or run
|
||||
|
||||
::
|
||||
|
||||
@py self.cmdset.delete('game.gamesrc.commands.mycmdset.MyCmdSet')
|
||||
|
||||
For more permanent addition, read the `step-by-step
|
||||
guide <Commands#Adding%3Ci%3Ea%3C/i%3Enew%3Ci%3Ecommand%3C/i%3E-%3Ci%3Ea%3C/i%3Estep%3Ci%3Eby%3C/i%3Estep_guide.html>`_
|
||||
below. Generally you can customize which command sets are added to your
|
||||
objects by using ``self.cmdset.add()`` or ``self.cmdset.add_default()``.
|
||||
|
||||
Adding a new command - a step by step guide
|
||||
-------------------------------------------
|
||||
|
||||
This is a summary of the information from the previous sections. Let's
|
||||
assume you have just downloaded Evennia and wants to try to add a new
|
||||
command to use. This is the way to do it.
|
||||
|
||||
#. In ``game/gamesrc/commands``, create a new module. Name it, say,
|
||||
``mycommand.py``.
|
||||
#. Import ``game.gamesrc.commands.basecommands.MuxCommand`` (this is a
|
||||
convenient shortcut so you don't have to import from src/ directly).
|
||||
The ``MuxCommand`` class handles command line parsing for you, giving
|
||||
you stuff like /switches, the syntax using '=' etc). In other words,
|
||||
you don't have to implement ``parse()`` on your own.
|
||||
#. Create a new class in ``mycommand`` that inherits from
|
||||
``MuxCommand``.
|
||||
#. Set the class variable ``key`` to the name to call your command with,
|
||||
say ``mycommand``.
|
||||
#. Set the ``locks`` property on the command to a suitable
|
||||
`lockstring <Locks#Defining%3Ci%3Elocks.html>`_. If you are unsure,
|
||||
use "cmd:all()".
|
||||
#. Define a class method ``func()`` that does stuff. See below.
|
||||
#. Give your class a useful *doc*\_ string, this acts as the help entry
|
||||
for the command.
|
||||
|
||||
Your command definition is now ready. Here's an example of how it could
|
||||
look:
|
||||
|
||||
::
|
||||
|
||||
from game.gamesrc.commands.basecommand import MuxCommandclass MyCommand(MuxCommand): """ Simple command example Usage: mycommand <text> This command simply echoes text back to the caller. (this string is also the help text for the command) """ key = "mycommand" locks = "cmd:all()" def func(self): "This actually does things" if not self.args: self.caller.msg("You didn't enter anything!") else: self.caller.msg("You gave the string: '%s'" % self.args)
|
||||
|
||||
Next we want to make this command available to us. There are many ways
|
||||
to do this, but all of them involves putting this command in a *Command
|
||||
Set*. First, let's try the more involved way.
|
||||
|
||||
#. Create a class that inherits from
|
||||
``game.gamesrc.commands.basecmdset.CmdSet``.
|
||||
#. (Optionally) set a key to name your command set.
|
||||
#. Add a method ``at_cmdset_creation()`` and use the ``self.add()``
|
||||
method to add your command to the command set.
|
||||
|
||||
This is what we have now:
|
||||
|
||||
::
|
||||
|
||||
from game.gamesrc.commands.basecmdset import CmdSet
|
||||
from game.gamesrc.commands import mycommandclass MyCmdSet(CmdSet): key = "MyCmdSet" def at_cmdset_creation(self): self.add(mycommand.MyCommand())
|
||||
|
||||
This new command set could of course contain any number of commands. We
|
||||
will now temporarily *merge* this command set to your current set. This
|
||||
is a convenient way to test cmdsets without messing with your default
|
||||
setup - if you reset those extra comands will be gone again.
|
||||
|
||||
Log into your game (as user #1) and add the cmdset to yourself like
|
||||
this:
|
||||
|
||||
::
|
||||
|
||||
@py self.cmdset.add('game.gamesrc.commands.mycmdset.MyCmdSet')
|
||||
|
||||
There, you should now be able to run the ``mycommand`` command.
|
||||
|
||||
To remove a cmdset, use ``self.cmdset.delete()``. This will remove the
|
||||
latest set (you can also name the set to remove, this where the cmdset's
|
||||
key comes in handy).
|
||||
|
||||
You can replace an object's default command set with this command:
|
||||
|
||||
::
|
||||
|
||||
@py self.search("myobject").cmdset.add_default('game.gamesrc.commands.mycmdset.MyCmdSet')
|
||||
|
||||
If you want to this to survive a server shutdown, use the ``permanent``
|
||||
keyword:
|
||||
|
||||
::
|
||||
|
||||
@py self.search("myobject").cmdset.add_default('game.gamesrc.commands.mycmdset.MyCmdSet', permanent=True)
|
||||
|
||||
The default cmdset is never affected by ``cmdset.add()`` or
|
||||
``cmdset.delete()``, you have to use ``cmdset.add_default()`` to set it
|
||||
explicitly (use ``remove_default()`` to remove it). Be careful to
|
||||
replace or remove the default cmdset on yourself unless you really know
|
||||
what you are doing - you will loose all the default Evennia commands and
|
||||
might not be able to get them back ...
|
||||
|
||||
And finally,
|
||||
|
||||
::
|
||||
|
||||
@reload
|
||||
|
||||
to update the server to your changes.
|
||||
|
||||
Appending a new command to the default command set
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Instead of manually appending your custom cmdset you can choose to
|
||||
extend Evennia's default command set directly. That way your new command
|
||||
will be loaded every server start along with all the other default
|
||||
commands.
|
||||
|
||||
The default command set is found in
|
||||
``src/commands/default/cmdset_default.py`` but there is already a
|
||||
shortcut to it in ``gamesrc/commands/basecmdset.py`` called
|
||||
``DefaultCmdSet``. Add your command to the end of the ``DefaultSet``
|
||||
class and you will in fact append it to the existing command set.
|
||||
|
||||
::
|
||||
|
||||
# file gamesrc/commands/basecmdset.py ... from game.gamesrc.commands import mycommandclass DefaultSet(BaseDefaultSet): key = DefaultMUX def at_cmdset_creation(self): # this first adds all default commands super(DefaultSet, self).at_cmdset_creation() # all commands added after this point will extend or # overwrite the default commands. self.add(mycommand.MyCommand())
|
||||
|
||||
Again, you need to run the ``@reload`` command to make these changes
|
||||
available.
|
||||
|
||||
Editing/replacing an existing default command
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This works the same way as in the previous section. Just set your new
|
||||
command class' ``key`` variable to be the same as that of the command to
|
||||
replace. So if you want to replace the default ``look`` command, just
|
||||
make sure to set your new command's ``key`` variable to ``look`` as
|
||||
well.
|
||||
|
||||
If you want to expand/build on the original command, just copy&paste its
|
||||
command class from ``src/commands/default``(the ``look`` class is for
|
||||
example found in ``src/commands/default/general.py``) into
|
||||
``game/gamesrc/commands`` and edit it there.
|
||||
|
||||
Adding and merging command sets
|
||||
-------------------------------
|
||||
|
||||
*Note: This is an advanced topic. It's useful to know about, but you
|
||||
might want to skip it if this is your first time learning about
|
||||
commands.*
|
||||
|
||||
CmdSets have the special ability that they can be *merged* together into
|
||||
new sets. This would happen if you, for example, did
|
||||
``object.cmdset.add(MyCmdSet)`` on an object that already had a command
|
||||
set defined on it. The two sets will be evaluated and a temporary,
|
||||
*merged set* will be created out of the commands in both sets. Only the
|
||||
commands in this merged set is from that point available to use. Which
|
||||
of the ingoing commands end up in the merged set is defined by the
|
||||
*merge rule* and the relative *priorities* of the two sets. Removing the
|
||||
latest added set will restore things back to the way it was before the
|
||||
addition.
|
||||
|
||||
CmdSets are non-destructively stored in a stack inside the cmdset
|
||||
handler on the object. This stack is parsed to create the "combined"
|
||||
cmdset active at the moment. The very first cmdset in this stack is
|
||||
called the *Default cmdset* and is protected from accidental deletion.
|
||||
Running ``obj.cmdset.delete()`` will never delete the default set.
|
||||
Instead one should add new cmdsets on top of the default to "hide" it,
|
||||
as described below. Use the special ``obj.cmdset.delete_default()`` only
|
||||
if you really know what you are doing.
|
||||
|
||||
CmdSet merging is an advanced feature useful for implementing powerful
|
||||
game effects. Imagine for example a player entering a dark room. You
|
||||
don't want the player to be able to find everything in the room at a
|
||||
glance - maybe you even want them to have a hard time to find stuff in
|
||||
their backpack! You can then define a different CmdSet with commands
|
||||
that override the normal ones. While they are in the dark room, maybe
|
||||
the ``look`` and ``inv`` commands now just tell the player they cannot
|
||||
see anything! Another example would be to offer special combat commands
|
||||
only when the player is in combat. Or when being on a boat. Or when
|
||||
having taken the super power-up. All this can be done on the fly by
|
||||
merging command sets.
|
||||
|
||||
Merge rules
|
||||
^^^^^^^^^^^
|
||||
|
||||
To understand how sets merge, we need to define a little lingo. Let's
|
||||
call the first command set **A** and the second **B**. We will merge
|
||||
**A** onto **B**, so in code terms the command would be
|
||||
``object.cdmset.add(A)``, where we assume **B** was already the active
|
||||
cmdset on ``object`` since earlier.
|
||||
|
||||
We let the **A** set have higher priority than **B**. A priority is
|
||||
simply an integer number. Default is 0, Evennia's in-built high-prio
|
||||
commands (intended to overrule others) have values of 9 or 10.
|
||||
|
||||
Both sets contain a number of commands named by numbers, like ``A1, A2``
|
||||
for set **A** and ``B1, B2, B3, B4`` for **B**. So for that example both
|
||||
sets contain commands with the same keys 1 and 2, whereas commands 3 and
|
||||
4 are unique to **B**. To describe a merge between these sets, we would
|
||||
write ``A1,A2 + B1,B2,B3,B4 = ?`` where ``?`` is a list of commands that
|
||||
depend on which merge type **A** has, and which relative priorities the
|
||||
two sets have. By convention, we read this statement as "New command set
|
||||
**A** is merged onto the old command set **B** to form **?**".
|
||||
|
||||
Below are the available merge types and how they work. Names are partly
|
||||
borrowed from `Set theory <http://en.wikipedia.org/wiki/Set_theory>`_.
|
||||
|
||||
**Union** (default) - The two cmdsets are merged so that as many
|
||||
commands as possible from each cmdset ends up in the merged cmdset.
|
||||
Same-key commands are merged by priority.
|
||||
|
||||
::
|
||||
|
||||
# Union A1,A2 + B1,B2,B3,B4 = A1,A2,B3,B4
|
||||
|
||||
**Intersect** - Only commands found in *both* cmdsets (i.e. which have
|
||||
the same keys) end up in the merged cmdset, with the higher-priority
|
||||
cmdset replacing the lower one's commands.
|
||||
|
||||
::
|
||||
|
||||
# Intersect A1,A3,A5 + B1,B2,B4,B5 = A1,A5
|
||||
|
||||
**Replace** - The commands of the higher-prio cmdset completely replaces
|
||||
the lower-priority cmdset's commands, regardless of if same-key commands
|
||||
exist or not.
|
||||
|
||||
::
|
||||
|
||||
# Replace A1,A3 + B1,B2,B4,B5 = A1,A3
|
||||
|
||||
**Remove** - The high-priority command sets removes same-key commands
|
||||
from the lower-priority cmdset. They are not replaced with anything, so
|
||||
this is a sort of filter that prunes the low-prio set using the
|
||||
high-prio one as a template.
|
||||
|
||||
::
|
||||
|
||||
# Remove A1,A3 + B1,B2,B3,B4,B5 = B2,B4,B5
|
||||
|
||||
Besides ``priority`` and ``mergetype``, a command set also takes a few
|
||||
other variables to control how they merge:
|
||||
|
||||
- *allow*duplicates*(bool) - determines what happens when two sets of
|
||||
equal priority merge. Default is that the new set in the merger (i.e.
|
||||
**A** above) automatically takes precedence. But if*allow*duplicates*
|
||||
is true, the result will be a merger with more than one of each name
|
||||
match. This will usually lead to the player receiving a
|
||||
multiple-match error higher up the road, but can be good for things
|
||||
like cmdsets on non-player objects in a room, to allow the system to
|
||||
warn that more than one 'ball' in the room has the same 'kick'
|
||||
command defined on it, so it may offer a chance to select which ball
|
||||
to kick ... Allowing duplicates only makes sense for *Union* and
|
||||
*Intersect*, the setting is ignored for the other mergetypes.
|
||||
- *key*mergetype*(dict) - allows the cmdset to define a unique
|
||||
mergetype for particular cmdsets, identified by their cmdset-key.
|
||||
Format is ``CmdSetkey:mergetype``. Priorities still apply. Example:
|
||||
``'Myevilcmdset','Replace'`` which would make sure for this set to
|
||||
always use 'Replace' on ``Myevilcmdset`` only, no matter
|
||||
what*mergetype\_ is set to.
|
||||
|
||||
More advanced cmdset example:
|
||||
|
||||
::
|
||||
|
||||
class MyCmdSet(CmdSet): key = "MyCmdSet" priority = 4 mergetype = "Replace" key_mergetype = 'MyOtherCmdSet':'Union' def at_cmdset_creation(self): """ The only thing this method should need to do is to add commands to the set. """ self.add(mycommands.MyCommand1()) self.add(mycommands.MyCommand2()) self.add(mycommands.MyCommand3())
|
||||
|
||||
System commands
|
||||
---------------
|
||||
|
||||
*Note: This is an advanced topic. Skip it if this is your first time
|
||||
learning about commands.*
|
||||
|
||||
There are several command-situations that are exceptional in the eyes of
|
||||
the server. What happens if the player enters an empty string? What if
|
||||
the 'command' given is infact the name of a channel the user wants to
|
||||
send a message to? Or maybe the name of an exit they want to traverse?
|
||||
|
||||
Such 'special cases' are handled by what's called *system commands*. A
|
||||
system command is defined in the same way as other commands, except that
|
||||
their name (key) must be set to one reserved by the engine (the names
|
||||
are defined at the top of ``src/commands/cmdhandler.py``). You can find
|
||||
(unused) implementations of the system commands in
|
||||
``src/commands/default/system_commands.py``. Since these are not (by
|
||||
default) included in any ``CmdSet`` they are not actually used, they are
|
||||
just there for show. When the special situation occurs, Evennia will
|
||||
look through all valid ``CmdSet``s for your custom system command. Only
|
||||
after that will it resort to its own, hard-coded implementation.
|
||||
|
||||
Here are the exceptional situations that triggers system commands:
|
||||
|
||||
- No input (``cmdhandler.CMD_NOINPUT``) - the player just pressed
|
||||
return without any input. Default is to do nothing, but it can be
|
||||
|
||||
useful for certain implementations such as line editors that interpret
|
||||
non-commands as text input.
|
||||
|
||||
- Command not found (``cmdhandler.CMD_NOMATCH``) - No matching command
|
||||
was found. Default is to display the "Huh?" error message.
|
||||
- Several matching commands where found (``cmdhandler.CMD_MULTIMATCH``)
|
||||
- Default is to show a list of matches.
|
||||
- User is not allowed to execute the command
|
||||
(``cmdhandler.CMD_NOPERM``) - Default is to display the "Huh?" error
|
||||
message.
|
||||
- Channel (``cmdhandler.CMD_CHANNEL``) - This is a
|
||||
`Channel <Communications.html>`_ name of a channel you are
|
||||
subscribing to - Default is to relay the command's argument to that
|
||||
channel. Such commands are created by the Comm system on the fly
|
||||
depending on your subscriptions.
|
||||
|
||||
Below is an example of redefining what happens when the player don't
|
||||
give any input (e.g. just presses return). Of course the new system
|
||||
command must be added to a cmdset as well before it will work.
|
||||
|
||||
::
|
||||
|
||||
from src.commands import cmdhandler from game.gamesrc.commands.basecommand import Commandclass MyNoInputCommand(Command): "Usage: Just press return, I dare you" key = cmdhandler.CMD_NOINPUT def func(self): self.caller.msg("Don't just press return like that, talk to me!")
|
||||
|
||||
How commands actually work
|
||||
--------------------------
|
||||
|
||||
*Note: This is an advanced topic mainly of interest to server
|
||||
developers.*
|
||||
|
||||
Any time the user sends text to Evennia, the server tries to figure out
|
||||
if the text entered corresponds to a known command. This is how the
|
||||
command handler sequence looks for a logged-in user:
|
||||
|
||||
A user (the *caller*) enters a string of text and presses enter.
|
||||
|
||||
- If input is an empty string, resend command as ``CMD_NOINPUT``. If no
|
||||
such command is found in cmdset, ignore.
|
||||
- If command.key matches ``settings.IDLE_COMMAND``, update timers but
|
||||
don't do anything more.
|
||||
|
||||
Evennia's *commandhandler* gathers the CmdSets available to *caller* at
|
||||
the time:
|
||||
|
||||
- The caller's own currently active !CmdSet.
|
||||
- The active CmdSets of eventual objects in the same location (if any).
|
||||
This includes commands on `Exits <Objects#Exits.html>`_.
|
||||
- Sets of dynamically created *System commands* representing available
|
||||
`Channels <Communications.html>`_.
|
||||
- !CmdSet defined on the *caller.player* (OOC cmdset).
|
||||
|
||||
All the CmdSets are *merged* into one combined CmdSet according to each
|
||||
set's merge rules.
|
||||
|
||||
Evennia's *command parser* takes the merged cmdset and matches each of
|
||||
its commands (using its key and aliases) against the beginning of the
|
||||
string entered by *caller*. This produces a set of candidates.
|
||||
|
||||
The *cmd parser* next rates the matches by how many characters they have
|
||||
and how many percent matches the respective known command. Only if
|
||||
candidates cannot be separated will it return multiple matches.
|
||||
|
||||
- If multiple matches were returned, resend as ``CMD_MULTIMATCH``. If
|
||||
no such command is found in cmdset, return hard-coded list of
|
||||
matches.
|
||||
- If no match was found, resend as ``CMD_NOMATCH``. If no such command
|
||||
is found in cmdset, give hard-coded error message.
|
||||
|
||||
If a single command was found by the parser, the correct command class
|
||||
is plucked out of storage and instantiated.
|
||||
|
||||
It is checked that the caller actually has access to the command by
|
||||
validating the *lockstring* of the command. If not, it is not considered
|
||||
as a suitable match it is resent as ``CMD_NOPERM`` is created. If no
|
||||
such command is found in cmdset, use hard-coded error message.
|
||||
|
||||
If the new command is tagged as a channel-command, resend as
|
||||
``CMD_CHANNEL``. If no such command is found in cmdset, use hard-coded
|
||||
implementation.
|
||||
|
||||
Assign several useful variables to the command instance.
|
||||
|
||||
Call ``at_pre_command()`` on the command instance.
|
||||
|
||||
Call ``parse()`` on the command instance. This is is fed the remainder
|
||||
of the string, after the name of the command. It's intended to pre-parse
|
||||
the string int a form useful for the ``func()`` method.
|
||||
|
||||
Call ``func()`` on the command instance. This is the functional body of
|
||||
the command, actually doing useful things.
|
||||
|
||||
Call ``at_post_command()`` on the command instance.
|
||||
130
docs/sphinx/source/wiki/Communications.rst
Normal file
130
docs/sphinx/source/wiki/Communications.rst
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
<wiki:toc max*depth*
|
||||
|
||||
"3" />
|
||||
======
|
||||
|
||||
Communications
|
||||
|
||||
Apart from moving around in the game world and talking, players might
|
||||
need other forms of communication. This is offered by Evennia's ``Comm``
|
||||
system. Stock evennia implements a 'MUX-like
|
||||
|
||||
::
|
||||
|
||||
system of channels, but there is nothing stopping you from changing things to better suit your taste. Comms rely on two main database objects -
|
||||
|
||||
Msg``and``Channel
|
||||
|
||||
::
|
||||
|
||||
. == Msg ==The
|
||||
|
||||
Msg
|
||||
|
||||
::
|
||||
|
||||
object is the basic unit of communication in Evennia. A message works a little like an e-mail; it always has a sender (a [Players Player]) and one or more recipients. The recipients may be either other Players, or a _Channel_ (see below). You can mix recipients to send the message to both Channels and Players if you like.Once created, a
|
||||
|
||||
Msg
|
||||
|
||||
::
|
||||
|
||||
is normally not changed. It is peristently saved in the database. This allows for comprehensive logging of communications, both in channels, but also for allowing senders/receivers to have 'mailboxes' with the messages they want to keep. === Properties defined on
|
||||
|
||||
Msg
|
||||
|
||||
::
|
||||
|
||||
=== *
|
||||
|
||||
sender
|
||||
|
||||
::
|
||||
|
||||
- this is a reference to a unique [Players Player] object sending the message. *
|
||||
|
||||
receivers
|
||||
|
||||
::
|
||||
|
||||
- a list of target [Players] to send to. *
|
||||
|
||||
channels
|
||||
|
||||
::
|
||||
|
||||
- a list of target Channels to send to. *
|
||||
|
||||
message
|
||||
|
||||
::
|
||||
|
||||
- the actual text being sent *
|
||||
|
||||
datesent
|
||||
|
||||
::
|
||||
|
||||
- when message was sent. *
|
||||
|
||||
locks
|
||||
|
||||
::
|
||||
|
||||
- a [Locks lock definition]. The following is currently unimplemented in Evennia (stay tuned): * hide_from_sender - bool if message should be hidden from sender * hide_from_receivers - list of receiver objects to hide message from * hide_from_channels - list of channels objects to hide message fromYou create new messages in code using
|
||||
|
||||
src.utils.create.create*message.*
|
||||
|
||||
::
|
||||
|
||||
===!TempMsg===
|
||||
|
||||
src.objects.models``contains a class called``TempMsg``that mimics a``Msg``but does not get saved to the database and do not require a sender object of a certain type. It's not used by default, but you could use it in code to send one-off messages to systems expecting a``Msg
|
||||
|
||||
::
|
||||
|
||||
.== Channels == Channels act as generic distributors of messages. Players _subscribe_ to channels and can then send and receive message from it. Channels have [Locks] to limit who may join them. There are three default channels created in stock Evennia -
|
||||
|
||||
MUDinfo``,``MUDconnections``and``Public
|
||||
|
||||
::
|
||||
|
||||
. Two first ones are server-related messages meant for Admins, the last one is open to everyone to chat on (all new players are automatically joined to it when logging in, useful for asking questions). You create new channels with
|
||||
|
||||
src.utils.create.createchannel()
|
||||
|
||||
::
|
||||
|
||||
.In code, messages are sent to a channel using the
|
||||
|
||||
msg(message, fromobj
|
||||
|
||||
None)``method. The argument``message``can either be a previously constructed``Msg``object or a message string. If you send a text string, you should usually also define``fromobj``; a``Msg``object will then be created for you behind the scenes. If you don't supply``from\_obj``, just the string will be sent to the channel and nothing will be stored in the database (could be useful for certain spammy error messages). You can also use``channel.tempmsg()``to always send a non-persistent message, also if you send it a``Msg
|
||||
|
||||
::
|
||||
|
||||
object.# assume we have a 'sender' object and a channel named 'mychan'# send and store in database from src.utils import create mymsg = create.create_message(sender, "Hello!", channels=[mychan]) mychan.msg(mymsg)# send a one-time message mychan.msg("Hello!")# send a one-time message created from a Msg object mychan.tempmsg(mymsg)
|
||||
|
||||
As a more advanced note, sending text to channels is a "special
|
||||
exception" as far as commands are concerned, and you may completely
|
||||
customize how this works by defining a *system*command\_ with your own
|
||||
code. See `Commands <Commands.html>`_ for more details.
|
||||
|
||||
Properties defined on ``Channel``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- ``key`` - main name for channel
|
||||
- ``aliases`` - alternative native names for channels
|
||||
- ``desc`` - optional description of channel (seen in listings)
|
||||
- ``keep_log`` (bool) - if the channel should store messages (default)
|
||||
- ``locks`` - A `lock definition <Locks.html>`_. Channels normally use
|
||||
the access\_types ``send, admin`` and ``listen``.
|
||||
|
||||
External Connections
|
||||
====================
|
||||
|
||||
Channels may also communicate through what is called an *External
|
||||
Connection*. Whereas normal users send messages through in-game Evennia
|
||||
commands, an external connection instead takes data from a remote
|
||||
location. `IMC2 <IMC2.html>`_ and `IRC <IRC.html>`_ connections make use
|
||||
of this.
|
||||
30
docs/sphinx/source/wiki/ConnectionScreen.rst
Normal file
30
docs/sphinx/source/wiki/ConnectionScreen.rst
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
The Connection Screen
|
||||
=====================
|
||||
|
||||
When you first connect to your game you are greeted by Evennia's default
|
||||
connection screen. It welcomes you, gives you the server version and
|
||||
tells you how to connect. Effective, but not very exciting. You will
|
||||
most likely want to change this to be more unique for your game.
|
||||
|
||||
You can customize the connection screen easily. If you look in
|
||||
``game/gamesrc/world`` you will find a module named
|
||||
``connection_screens.py``. Evennia looks into this module for globally
|
||||
defined strings (only). These strings are used as connection screens and
|
||||
shown to the user at startup. If more than one screen is defined in the
|
||||
module, a random screen will be picked from among those available.
|
||||
|
||||
Evennia's default screen is imported as ``DEFAULT_SCREEN`` from
|
||||
``src.commands.connection_screen``. Remove the import or redefine
|
||||
``DEFAULT_SCREEN`` to get rid of the default. There is a commented-out
|
||||
example screen in the module that you can start from. You can define and
|
||||
import things as normal into the module, but remember that *all* global
|
||||
strings will be picked up and potentially used as a connection screen.
|
||||
You can change which module Evennia uses by changing
|
||||
``settings.CONNECTION_SCREEN_MODULE``.
|
||||
|
||||
You can also customize the `commands <Commands.html>`_ available during
|
||||
the connection screen (``connect``, ``create`` etc). These commands are
|
||||
a bit special since when the screen is running the player is not yet
|
||||
identified. A command is made available at the login screen by adding
|
||||
them to the command set specified by settings.CMDSET\_UNLOGGEDIN. The
|
||||
default commands are found in ``src/commands/default/unloggedin.py``.
|
||||
58
docs/sphinx/source/wiki/Contributing.rst
Normal file
58
docs/sphinx/source/wiki/Contributing.rst
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
Wanna help out? Great! Here's how.
|
||||
|
||||
Contributing with Documentation
|
||||
===============================
|
||||
|
||||
Evennia depends heavily on good documentation and we are always looking
|
||||
for extra eyes and hands to improve it. Even a small thing such as
|
||||
fixing typos is a great help.
|
||||
|
||||
Contributing with Code
|
||||
======================
|
||||
|
||||
Code sharing with Clone repository
|
||||
----------------------------------
|
||||
|
||||
The most elegant way to contribute code to Evennia is to use Mercurial
|
||||
to create an online *clone* of the Evennia repository and make your
|
||||
changes to that. .
|
||||
|
||||
#. Go to the
|
||||
`Checkout <http://code.google.com/p/evennia/source/checkout>`_ page.
|
||||
#. If you are logged in, you should see a button named *Create a Clone*.
|
||||
Click that.
|
||||
#. You are asked to fill in a few fields. Name your clone repository
|
||||
something snazzy. Give a brief summary, like "my repo for messing
|
||||
around with Evennia". Accept.
|
||||
#. Your new repo is created. This is actually your own mini-version of
|
||||
the Evennia page! Go to your checkout page and use the command there
|
||||
to get a local copy of your clone to your computer.
|
||||
#. Code away on your computer, fixing bugs or whatnot (you can be
|
||||
offline for this). Commit your code to your local clone as you work,
|
||||
as often as you like.
|
||||
#. When you have something you feel is worthwhile (or just want to ask
|
||||
people's opinions or make an online backup), *push* your local code
|
||||
up to your online repository with Mercurial.
|
||||
#. Let people know what you did, talk discuss. If you think your changes
|
||||
should be merged into main Evennia (maybe you have made bugfixes,
|
||||
added new features etc), make a new
|
||||
`Issue <http://code.google.com/p/evennia/issues/list>`_ using the
|
||||
"Merge Request" template. Try to separate features with different
|
||||
commits, so it's possible to pick individual features.
|
||||
|
||||
From your online repo, Evennia devs can then, assuming the change is
|
||||
deemed good, pick and merge your work into Evennia proper.
|
||||
|
||||
Patches
|
||||
-------
|
||||
|
||||
It's recommended to use a clone repository as described above. Otherwise
|
||||
you are also welcome to submit your suggested Evennia fixes/addendums as
|
||||
`patches <https://secure.wikimedia.org/wikipedia/en/wiki/Patch_(computing).html>`_
|
||||
if you like. Depending on what fits best, post your patch to the `issue
|
||||
tracker <https://code.google.com/p/evennia/issues/list.html>`_ or to the
|
||||
`discussion
|
||||
forum <https://groups.google.com/forum/#!forum/evennia.html>`_. Please
|
||||
avoid pasting the full patch text directly in your post though, best is
|
||||
to use a site like `Pastebin <http://pastebin.com/>`_ and just supply
|
||||
the link.
|
||||
1262
docs/sphinx/source/wiki/DefaultCommandHelp.rst
Normal file
1262
docs/sphinx/source/wiki/DefaultCommandHelp.rst
Normal file
File diff suppressed because it is too large
Load diff
79
docs/sphinx/source/wiki/DeveloperCentral.rst
Normal file
79
docs/sphinx/source/wiki/DeveloperCentral.rst
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
Developer Central
|
||||
=================
|
||||
|
||||
This page serves as a central nexus for useful information regarding
|
||||
coding using the Evennia codebase, and also for development of the
|
||||
codebase itself. Everyone is welcome to help out! If you have any
|
||||
questions, please feel free to ask them in the `Forum/Discussion
|
||||
Group <http://www.evennia.com/discussions>`_. Bugs should be reported to
|
||||
the `Issue tracker <http://code.google.com/p/evennia/issues/list>`_. You
|
||||
can find more links to Evennia resources from the `Links <Links.html>`_
|
||||
page.
|
||||
|
||||
General Evennia development information
|
||||
---------------------------------------
|
||||
|
||||
- `Evennia Licensing FAQ <Licensing.html>`_
|
||||
- `Contributing code to Evennia <Contributing.html>`_
|
||||
- `Evennia Code Style
|
||||
Guide <http://evennia.googlecode.com/svn/trunk/CODING_STYLE>`_
|
||||
(Important!)
|
||||
- `Policy for 'MUX-like' default commands <UsingMUXAsAStandard.html>`_
|
||||
|
||||
<wiki:comment>
|
||||
|
||||
- `Setting up a Bazaar environment for coding <BazaarDevel.html>`_
|
||||
|
||||
</wiki:comment>
|
||||
|
||||
Evennia Component Documentation
|
||||
-------------------------------
|
||||
|
||||
`Directory Overview <DirectoryOverview.html>`_
|
||||
|
||||
`Portal and Server <PortalAndServer.html>`_
|
||||
|
||||
`Commands <Commands.html>`_
|
||||
|
||||
`Typeclass system <Typeclasses.html>`_
|
||||
|
||||
- `Objects <Objects.html>`_
|
||||
- `Scripts <Scripts.html>`_
|
||||
- `Players <Players.html>`_
|
||||
- `Attributes <Attributes.html>`_
|
||||
|
||||
`Locks and Permissions <Locks.html>`_
|
||||
|
||||
`Communications <Communications.html>`_
|
||||
|
||||
`Help System <HelpSystem.html>`_
|
||||
|
||||
`Nicks <Nicks.html>`_
|
||||
|
||||
`Sessions and Protocols <SessionProtocols.html>`_
|
||||
|
||||
`Web features <WebFeatures.html>`_
|
||||
|
||||
Programming Evennia
|
||||
-------------------
|
||||
|
||||
- `Running and Testing Python code from inside the
|
||||
game <ExecutePythonCode.html>`_
|
||||
- `Running and writing unit tests for Evennia <UnitTesting.html>`_
|
||||
- `Removing Colour from your game - tutorial on redefining typeclass
|
||||
methods <RemovingColour.html>`_
|
||||
- `Adding a Command prompt <CommandPrompt.html>`_
|
||||
- `Running processes asynchronously <AsyncProcess.html>`_
|
||||
|
||||
Work in Progress - Developer brainstorms and whitepages
|
||||
-------------------------------------------------------
|
||||
|
||||
*In this section, contributors may suggest, discuss and plan out new
|
||||
features and ideas. Items here may or may not make it into Evennia down
|
||||
the road.*
|
||||
|
||||
- `Basic game system implementation <WorkshopDefaultGame.html>`_
|
||||
- `Rtclient protocol <Workshop.html>`_
|
||||
- `Summary of changes <EvenniaDevel.html>`_ of latest version vs old
|
||||
Evennia (pre aug2010)
|
||||
|
||||
274
docs/sphinx/source/wiki/DirectoryOverview.rst
Normal file
274
docs/sphinx/source/wiki/DirectoryOverview.rst
Normal file
|
|
@ -0,0 +1,274 @@
|
|||
Evennia directory overview
|
||||
==========================
|
||||
|
||||
Evennia's main directory (``evennia``) is divided into four sub
|
||||
directories - ``src/``, ``game/``, ``contrib/``, ``locale`` and
|
||||
``doc/``. The first two are the most important ones. ``game/`` is the
|
||||
place where you will create your own game, whereas ``src/`` is the home
|
||||
of the Evennia server itself. Your code should usually just import
|
||||
resources from ``src/`` and not change anything in there.
|
||||
|
||||
All directories contain files ending in ``.py``. These are Python
|
||||
*modules* and are the basic units of Python code. The roots of
|
||||
directories also have empty files named ``__init__.py``. These are
|
||||
required by Python so as to be able to find and import modules in other
|
||||
directories. When you have run Evennia at least once you will find that
|
||||
there will also be ``.pyc`` files appearing, these are pre-compiled
|
||||
binary versions of the ``.py`` files to speed up execution.
|
||||
|
||||
The ``docs/`` directory
|
||||
-----------------------
|
||||
|
||||
You may have noticed that ``docs/`` is pretty empty. This is because you
|
||||
are in fact reading the docs right now - this wiki *is* the
|
||||
documentation.
|
||||
|
||||
You can create the *autodocs* of Evennia by following the instructions
|
||||
in ``docs/README``. This will make use of the source code itself to
|
||||
create a nice browsable web-index of all the sources and comments. In
|
||||
the same way you could in theory also create nice ``LaTeX``-formatted
|
||||
PDFs of the Evennia source (all 300+ pages of it ...).
|
||||
|
||||
The ``locale`` directory
|
||||
------------------------
|
||||
|
||||
This contains internationalization strings for translating the Evennia
|
||||
core server to different languages. See
|
||||
`Internationalization <Internationalization.html>`_ for more
|
||||
information.
|
||||
|
||||
The ``contrib/`` ("contributions") directory
|
||||
--------------------------------------------
|
||||
|
||||
This directory contains various stand-alone code snippets that are
|
||||
potentially useful but which are deemed too game-specific to be a
|
||||
regular part of the server. Modules in ``contrib/`` are not used unless
|
||||
you explicitly import and use them. The contrib folder also contains the
|
||||
`Tutorial World <TutorialWorldIntroduction.html>`_ game example. See
|
||||
``contrib/README`` for more information.
|
||||
|
||||
The ``game/`` directory
|
||||
-----------------------
|
||||
|
||||
``game/`` contains everything related to a particular game world. If you
|
||||
ever wanted to start over with a new game implementation you could
|
||||
replace the ``game`` directory and start from scratch. The root of this
|
||||
directory contains the all-important ``manage.py`` and ``evennia.py``
|
||||
which you need in order to `get started <GettingStarted.html>`_ and run
|
||||
the server.
|
||||
|
||||
::
|
||||
|
||||
game/
|
||||
evennia.py
|
||||
manage.py gamesrc/ commands/ basecommand.py basecmdset.py examples/ cmdset_red_button.py scripts/ basescript.py examples/ red_button_sripts.py objects/ baseobjects.py examples/ red_button.py world/ examples/ batch_cmds.ev batch_code.py
|
||||
|
||||
``game/gamesrc/``
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
``game/gamesrc`` is where you will be spending most of your time. All
|
||||
the things going into your own dream game should be put here, by adding
|
||||
Python modules. Throughout the ``gamesrc`` directories are ``examples``
|
||||
folders that all define different aspects of an example
|
||||
`object <Objects.html>`_ called *Red Button*. This is a button that
|
||||
blinks and does interesting stuff when pressed. It's designed to combine
|
||||
many different systems and to show off several advanced features of
|
||||
Evennia.
|
||||
|
||||
``gamesrc/commands/``
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
``gamesrc/commands/`` contains modules for defining
|
||||
`Commands <Commands.html>`_. It contains a file ``basecommand.py`` which
|
||||
defines the root object from which all your own command classes will
|
||||
inherit.The file ``basecmdset.py`` is where you'll inherit your `Command
|
||||
Set <Commands.html>`_ classes from. ``commands/examples`` contains the
|
||||
main interactive commands and cmdsets of the *Red Button*.
|
||||
|
||||
``gamesrc/scripts/``
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
``gamesrc/scripts/`` holds everything related to
|
||||
`Scripts <Scripts.html>`_. It has a file ``basescript.py`` that hold the
|
||||
parent for all scripts and which you should inherit from.
|
||||
``scripts/examples`` holds the *Red Button*'s scripts.
|
||||
|
||||
``gamesrc/objects/``
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
``gamesrc/objects/`` should contain the definitions for all your
|
||||
`Objects <Objects.html>`_. ``baseobjects.py`` contains the parent
|
||||
classes for the normal *Object* as well as its three basic subclasses
|
||||
*Character*, *Room* and *Exit*. Your own objects will inherit from the
|
||||
classes in this file. ``objects/examples`` define the example *Red
|
||||
Button* object itself.
|
||||
|
||||
``gamesrc/world/``
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
``gamesrc/world/``, finally, contains all the rest that make up your
|
||||
world. This is where you would put your own custom economic system,
|
||||
combat mechanic, emote-parser or what have you; organized in whatever
|
||||
way you like. Just remember that if you create new folders under
|
||||
``world``, they must contain an empty file ``__init__.py``, or Python
|
||||
will not know how to import modules from them. The ``world`` folder is
|
||||
also where Evennia's `batch processors <BatchProcessors.html>`_ by
|
||||
default look for their input files. These allow you to build your world
|
||||
offline using your favourite text editor rather than have to do it
|
||||
online over a command line. The `Batch-Command
|
||||
processor <BatchCommandProcessor.html>`_ expects files ending with
|
||||
``.ev``, whereas the more advanced `Batch-Code
|
||||
processor <BatchCodeProcessor.html>`_ takes ``.py`` with some special
|
||||
formatting.
|
||||
|
||||
``world/examples/`` contains one batch file for each processor. Each
|
||||
creates a *Red Button* object in *Limbo* using their respective special
|
||||
syntax.
|
||||
|
||||
The ``src/`` directory
|
||||
----------------------
|
||||
|
||||
``src/`` contains the main running code of the Evennia server. You will
|
||||
often need to import modules from here to access the functionality of
|
||||
Evennia. You should generally not modify anything in this folder
|
||||
directly since it might be changed when we release updates. If you find
|
||||
bugs or features missing, file a bug report or send us a message.
|
||||
|
||||
::
|
||||
|
||||
src/
|
||||
settings_defaults.py commands/ comms/ help/ objects/ locks/ players/ scripts/ server/ typeclasses/ utils/ web/
|
||||
|
||||
Most of the folders in ``src/`` are technically "Django apps",
|
||||
identified by containing a file ``models.py`` and usually
|
||||
``managers.py``. A Django *model* is a template for how to save data to
|
||||
the database. In order to offer full-persistence, Evennia uses models
|
||||
extensively. The *manager* is used to conveniently access objects in the
|
||||
database. Even if you don't know Django, you can easily use the methods
|
||||
in the respective managers by accessing them through the *objects*
|
||||
property of each corresponding model. Example: in
|
||||
``src/objects/models.py`` there is a model named ``ObjectDB``. In the
|
||||
same folder, there is also a manager found in
|
||||
``src/objects/managers.py``. To access one of the manager's methods,
|
||||
such as ``object_search()``, you would need to do
|
||||
``ObjectDB.objects.object_search(...)``.
|
||||
|
||||
All Django app folders also have a file ``admin.py``. This tells
|
||||
Django's web features to automatically build a nice web-based admin
|
||||
interface to the database. This means that you can add/edit/delete
|
||||
objects through your browser.
|
||||
|
||||
In the root of the ``src`` directory lies the ``settings_defaults.py``
|
||||
file. This is the main configuration file of Evennia. You should
|
||||
copy&paste entries from this file to your ``game/settings.py`` file if
|
||||
you want to customize any setting.
|
||||
|
||||
``src/commands/``
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
This directory contains the `command system <Commands.html>`_ of
|
||||
Evennia. It defines basic command function, parsing and command-set
|
||||
handling.
|
||||
|
||||
``commands/default/`` holds a multitude of modules that together form
|
||||
Evennia's default ('`MUX-like <UsingMUXAsAStandard.html>`_') command
|
||||
set. The files ``game/gamesrc/basecommand.py`` and
|
||||
``game/gamesrc/basecmdset.py`` both link to their respective parents
|
||||
here. If you want to edit a default command, copy&paste the respective
|
||||
module to ``game/gamesrc/commands/`` and edit the default cmdset to
|
||||
point to your copy.
|
||||
|
||||
``src/comms/``
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
``src/comms/`` defines all aspects of OOC
|
||||
`communication <Communications.html>`_, notably *channels* and the basic
|
||||
operations for storing listeners to channels.
|
||||
|
||||
``src/help/``
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
This defines the `help system <HelpSystem.html>`_ of Evennia, the
|
||||
command auto-help as well as the database-centric storage of in-game
|
||||
help files.
|
||||
|
||||
``src/objects/``
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
``src/objects/`` defines how the in-game `objects <Objects.html>`_ are
|
||||
stored, found and handled in the database.
|
||||
|
||||
``src/locks/``
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
This directory defines the powerful `lock system <Locks.html>`_ of
|
||||
Evennia, a system that serves to restrict access to objects. The default
|
||||
lock functions are found here.
|
||||
|
||||
``src/players/``
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
The `Player <Players.html>`_ is the OOC-represention of the person
|
||||
behind the game character. This directory defines the database handling
|
||||
and methods acting on the Player object.
|
||||
|
||||
``src/scripts/``
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
``src/scripts/`` defines all aspects of `Scripts <Scripts.html>`_ - how
|
||||
they are activated, repeated and stored in-memory or in-database. The
|
||||
main engine scripts (e.g. for keeping track of game-time, uptime and
|
||||
connection timeouts) are also defined here.
|
||||
|
||||
``src/server/``
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
This directory is the heart of Evennia. It holds the server process
|
||||
itself (started from ``game/evennia.py``) and all `sessions and
|
||||
protocols <SessionProtocols.html>`_ that allow users to connect to it.
|
||||
It also knows how to store dynamic server info in the database.
|
||||
|
||||
``src/typeclasses/``
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
``src/typeclasses/`` defines the `Typeclass system <Typeclasses.html>`_
|
||||
that permeates Evennia, allowing coders to interact with normal Python
|
||||
classes instead of caring about the underlying database implementation.
|
||||
This directory is rarely accessed directly, rather both Objects, Scripts
|
||||
and Players all inherit from its core classes. Also
|
||||
`attributes <Attributes.html>`_ are defined here, being an vital part of
|
||||
the typeclass system.
|
||||
|
||||
``src/utils/``
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
``src/utils/`` is a useful directory that contains helper functions for
|
||||
the MUD coder. The ``utils/create.py`` module for example gathers
|
||||
methods for creating all sorts of database models (objects, scripts,
|
||||
help entries etc) without having to go into the respective database
|
||||
managers directly. ``utils/search.py`` search a similar function for
|
||||
searching the database. This directory also contains many helper modules
|
||||
for parsing and converting data in various ways.
|
||||
|
||||
``src/web/``
|
||||
~~~~~~~~~~~~
|
||||
|
||||
This directory contains features related to running Evennia's `web site
|
||||
and ajax web client <WebFeatures.html>`_. It will be customizable by the
|
||||
user, but it's currently not established how to conveniently hook into
|
||||
this from game/, so for the moment the suggested way is to make a copy
|
||||
of this directory in ``game/gamesrc``, re-link the right settings in
|
||||
your settings file and edit things from there.
|
||||
|
||||
Assorted notes
|
||||
==============
|
||||
|
||||
Whereas ``game/gamesrc/`` contains a set of directories already, you
|
||||
might find that another structure suits your development better. For
|
||||
example, it could sometimes easier to put all the commands and scripts a
|
||||
certain object needs in the same module as that object, rather than
|
||||
slavishly split them out into their respective directories and import.
|
||||
Don't be shy to define your own directory structure as needed. A basic
|
||||
rule of thumb should nevertheless be to avoid code-duplication. So if a
|
||||
certain script or command could be useful for other objects, break it
|
||||
out into its own module and import from it.
|
||||
372
docs/sphinx/source/wiki/EvenniaDevel.rst
Normal file
372
docs/sphinx/source/wiki/EvenniaDevel.rst
Normal file
|
|
@ -0,0 +1,372 @@
|
|||
Summary of changes in devel-branch
|
||||
|
||||
<wiki:toc max\_depth
|
||||
|
||||
"3" />
|
||||
|
||||
*Note: The devel branch merged with trunk as of r970. So if you are new
|
||||
to Evennia, this page is of no real interest to you.*
|
||||
|
||||
Introduction
|
||||
|
||||
The Evennia that has been growing in trunk for the last few years is a
|
||||
wonderful piece of software, with which you can do very nice coding
|
||||
work. It has however grown 'organically', adding features here and there
|
||||
by different coders at different times, and some features (such as my
|
||||
State system) were bolted onto an underlying structure for which it was
|
||||
never originally intended. Meanwhile Evennia is still in an alpha stage
|
||||
and not yet largely used. If one needs to do a cleanup/refactoring and
|
||||
homogenization of the code, now is the time time to do it. So I set out
|
||||
to do just that.
|
||||
|
||||
The "devel-branch" of Evennia is a clean rework of Evennia based on
|
||||
trunk. I should point out that the main goal has been to make system
|
||||
names consistent, to add all features in a fully integrated way, and to
|
||||
give all subsystems a more common API for the admin to work against.
|
||||
This means that in the choice between a cleaner implementation and
|
||||
backwards-compatability with trunk, the latter has had to stand back.
|
||||
However, you'll hopefully find that converting old codes shouldn't be
|
||||
too hard. Another goal is to further push Evennia as a full-fledged
|
||||
barebones system for *any* type of mud, not just MUX. So you'll find far
|
||||
more are now user-configurability now than ever before (MUX remains the
|
||||
default though).
|
||||
|
||||
Devel is now almost ready for merging with the main trunk, but it needs
|
||||
some more eyes to look at it first. If you are brave and want to help
|
||||
report bugs, you can get it from the *griatch* branch with
|
||||
|
||||
``svn checkout http://evennia.googlecode.com/svn/branches/griatch evennia-devel``
|
||||
|
||||
Concepts changed from trunk to devel=
|
||||
|
||||
Script parent -> Typeclasses
|
||||
----------------------------
|
||||
|
||||
The biggest change is probably that script parents have been replaced by
|
||||
*typeclasses*. Both handle the abstraction of in-game objects without
|
||||
having to create a separate database model for each (i.e. it allows
|
||||
objects to be anything from players to apples, rooms and swords all with
|
||||
the same django database model). A script parent in trunk was a class
|
||||
stored in a separate module together with a 'factory' function that the
|
||||
engine called. The admin had to always remember if they were calling a
|
||||
function on the database model or if it in fact sat on the script parent
|
||||
(the call was made through something called the "scriptlink").
|
||||
|
||||
By contrast, a typeclass is a normal python class that inherits from the
|
||||
*!TypeClass* parent. There are no other required functions to define.
|
||||
This class uses **getattribute** and **setattr** transparently behind
|
||||
the scenes to store data onto the persistent django object. Also the
|
||||
django model is aware of the typeclass in the reverse direction. The
|
||||
admin don't really have to worry about this connection, they can usually
|
||||
consider the two objects (typeclass and django model) to be one.
|
||||
|
||||
So if you have your 'apple' typeclass, accessing, say the 'location',
|
||||
which is stored as a persistent field on the django model, you can now
|
||||
just do ``loc = apple.location`` without caring where it is stored.
|
||||
|
||||
The main drawback with any typeclass/parent system is that it adds an
|
||||
overhead to all calls, and this overhead might be slightly larger with
|
||||
typeclasses than with trunk's script parents although I've not done any
|
||||
testing. You also need to use Evennia's supplied ``create`` methods to
|
||||
create the objects rather than to create objects with plain Django by
|
||||
instantiating the model class; this so that the rather complex
|
||||
relationships can be instantiated safely behind the scenes.
|
||||
|
||||
Command functions + !StateCommands-> Command classes + CmdSets
|
||||
--------------------------------------------------------------
|
||||
|
||||
In trunk, there was one default group of commands in a list
|
||||
GLOBAL*CMD*TABLE. Every player in game used this. There was a second
|
||||
dictionary GLOBAL*STATE*TABLE that held commands valid only for certain
|
||||
*states* the player might end up in - like entering a dark room, a text
|
||||
editor, or whatever. The problem with this state system, was that it was
|
||||
limited in its use - every player could ever only be in one state at a
|
||||
time for example, never two at the same time. The way the system was set
|
||||
up also explicitly made states something unique to players - an object
|
||||
could not offer different commands dependent on its state, for example.
|
||||
|
||||
In devel, *every* command definition is grouped in what's called a
|
||||
*!CmdSet* (this is, like most things in Devel, defined as a class). A
|
||||
command can exist in any number of cmdsets at the same time. Also the
|
||||
'default' group of commands belong to a cmdset. These command sets are
|
||||
no longer stored globally, but instead locally on each object capable of
|
||||
launching commands. You can add and new cmdsets to an object in a
|
||||
stack-like way. The cmdsets support set operations (Union, Difference
|
||||
etc) and will merge together into one cmdset with a unique set of
|
||||
commands. Removing a cmdset will re-calculate those available commands.
|
||||
This allows you to do things like the following (impossible in trunk): A
|
||||
player is walking down a corridor. The 'default' cmdset is in play. Now
|
||||
he meets an enemy. The 'combat' cmdset is merged onto (and maybe
|
||||
replacing part of) the default cmdset, giving him new combat-related
|
||||
commands only available during combat. The enemy hits him over the head,
|
||||
dazing him. The "Dazed" cmdset is now added on top of the previous ones
|
||||
- maybe he now can't use certain commands, or might even get a garbled
|
||||
message if trying to use 'look'. After a few moments the dazed state is
|
||||
over, and the 'Dazed' cmdset is removed, returning us to the combat mode
|
||||
we were in before. And so on.
|
||||
|
||||
Command definitions used to be functions, but are now classes. Instead
|
||||
of relying on input arguments, all relevant variables are stored
|
||||
directly on the command object at run-time. Also parsing and function
|
||||
execution have been split into two methods that are very suitable for
|
||||
subclassing (an example is all the commands in the default set which
|
||||
inherits from the MuxCommand class - that's the one knowing about MUX's
|
||||
special syntax with /switches, '=' and so on, Evennia's core don't deal
|
||||
with this at all!).
|
||||
|
||||
Example of new command definition:
|
||||
|
||||
::
|
||||
|
||||
class CmdTest(Command): def func(self): self.caller.msg("This is the test!")
|
||||
|
||||
Events + States -> Scripts
|
||||
--------------------------
|
||||
|
||||
The Event system of Evennia used to be a non-persistent affair; python
|
||||
objects that needed to be explicitly called from code when starting.
|
||||
States allowed for mapping different groups of commands to a certain
|
||||
situations (see CmdSets above for how commands are now always grouped).
|
||||
|
||||
*Scripts* (warning: Not to be confused with the old *script parents*!)
|
||||
are persistent database objects now and are only deleted on a server
|
||||
restart if explicitly marked as non-persistent.
|
||||
|
||||
A script can have a time-component, like Events used to have, but it can
|
||||
also work like an 'Action' or a 'State' since a script constantly checks
|
||||
if it is still 'valid' and if not will delete itself. A script handles
|
||||
everything that changes with time in Evennia. For example, all players
|
||||
have a script attached to them that assigns them the default cmdset when
|
||||
logging in.
|
||||
|
||||
Oh, and Scripts have typeclasses too, just like Objects, and carries all
|
||||
the same flexibility of the Typeclass system.
|
||||
|
||||
User + player -> User + Player + character
|
||||
------------------------------------------
|
||||
|
||||
In trunk there is no clear separation between the User (which is the
|
||||
django model representing the player connecting to the mud) and the
|
||||
player object. They are both forced to the same dbref and are
|
||||
essentially the same for most purposes. This has its advantages, but the
|
||||
problem is configurability for different game types - the in-game player
|
||||
object becomes the place to store also OOC info, and allowing a player
|
||||
to have many characters is a hassle (although doable, I have coded such
|
||||
a system for trunk privately). Devel-branch instead separate a "player
|
||||
character" into three tiers:
|
||||
|
||||
- The User (Django object)
|
||||
- The PlayerDB (User profile + Player typeclass)
|
||||
- The ObjectDB (+ Character typeclass)
|
||||
|
||||
User is not something we can get out of without changing Django; this is
|
||||
a permission/password sensitive object through which all Django users
|
||||
connect. It is not configurable to any great extent except through it's
|
||||
*profile*, a django feature that allows you to have a separate model
|
||||
that configures the User. We call this profile 'PlayerDB', and for
|
||||
almost all situations we deal with this rather than User. PlayerDB can
|
||||
hold attributes and is typeclassed just like Objects and Scripts
|
||||
(normally with a typeclass named simply *Player*) allowing very big
|
||||
configurability options (although you can probably get away with just
|
||||
the default setup and use attributes for all but the most exotic
|
||||
designs). The Player is an OOC entity, it is what chats on channels but
|
||||
is not visible in a room. The last stage is the in-game ObjectDB model,
|
||||
typeclassed with a class called 'Character' by default. This is the
|
||||
in-game object that the player controls.
|
||||
|
||||
The neat thing with this separation is that the Player object can easily
|
||||
switch its Character object if desired - the two are just linking to
|
||||
each other through attributes. This makes implementing multi-character
|
||||
game types much easier and less contrived than in the old system.
|
||||
|
||||
Help database -> command help + help database
|
||||
---------------------------------------------
|
||||
|
||||
Trunk stores all help entries in the database, including those created
|
||||
dynamically from the command's doc strings. This forced a system where
|
||||
the auto-help creation could be turned off so as to not overwrite later
|
||||
changes made by hand. There was also a mini-language that allowed for
|
||||
creating multiple help entries from the ``__doc__`` string.
|
||||
|
||||
Devel-branch is simpler in this regard. All commands are *always* using
|
||||
``__doc__`` on the fly at run time without hitting the database (this
|
||||
makes use of cmdsets to only show help for commands actually available
|
||||
to you). The help database is stand-alone and you can add entries to it
|
||||
as you like, the help command will look through both sources of help
|
||||
entries to match your query.
|
||||
|
||||
django-perms + locks -> permission/locks
|
||||
----------------------------------------
|
||||
|
||||
Trunk relies on Django's user-permissions. These are powerful but have
|
||||
the disadvantage of being 'app-centric' in a way that makes sense for a
|
||||
web app, not so much for a mud. The devel-branch thus implements a
|
||||
completely stand-alone permission system that incoorperate both
|
||||
permissions and locks into one go - the system uses a mini-language that
|
||||
has a permission string work as a keystring in one situation and as a
|
||||
complex lock (calling python lock functions you can define yourself) in
|
||||
another.
|
||||
|
||||
The permission system is working on a fundamental level, but the default
|
||||
setup probably needs some refinements still.
|
||||
|
||||
Mux-like comms -> Generic comms
|
||||
-------------------------------
|
||||
|
||||
The trunk comm system is decidedly MUX-like. This is fine, but the
|
||||
problem is that much of that mux-likeness is hard-coded in the engine.
|
||||
|
||||
Devel just defines three objects, Channel and Msg and an object to track
|
||||
connections between players and channels (this is needed to easily
|
||||
delete/break connections). How they interact with each other is up to
|
||||
the commands that use them, making the system completely configurable by
|
||||
the admin.
|
||||
|
||||
All ooc messages - to channels or to players or both at the same time,
|
||||
are sent through use of the Msg object. This means a full log of all
|
||||
communications become possible to keep. Other uses could be an e-mail
|
||||
like in/out box for every player. The default setup is still mux-like
|
||||
though.
|
||||
|
||||
Hard-coded parsing -> user customized parsing
|
||||
---------------------------------------------
|
||||
|
||||
Essentially all parts of parsing a command from the command line can be
|
||||
customized. The main parser can be replaced, as well as error messages
|
||||
for multiple-search matches. There is also a considerable difference in
|
||||
handling exits and channels - they are handled as commands with their
|
||||
separate cmdsets and searched with the same mechanisms as any command
|
||||
(almost any, anyway).
|
||||
|
||||
Aliases -> Nicks
|
||||
----------------
|
||||
|
||||
Aliases (that is, you choosing to for yourself rename something without
|
||||
actually changing the object itself) used to be a separate database
|
||||
table. It is now a dictionary 'nicks' on the Character object - that
|
||||
replace input commands, object names and channel names on the fly. And
|
||||
due to the separation between Player and Character, it means each
|
||||
character can have its own aliases (making this a suitable start for a
|
||||
recog system too, coincidentally).
|
||||
|
||||
Attributes -> properties
|
||||
------------------------
|
||||
|
||||
To store data persistently in trunk requires you to call the methods
|
||||
``get_attribute_value(attr)`` and ``set_attribute(attr, value)``. This
|
||||
is available for in-game Objects only (which is really the only data
|
||||
type that makes sense anyway in Trunk).
|
||||
|
||||
Devel allows attribute storage on both Objects, Scripts and Player
|
||||
objects. The attribute system works the same but now offers the option
|
||||
of using the ``db`` (for database) directly. So in devel you could now
|
||||
just do:
|
||||
|
||||
::
|
||||
|
||||
obj.db.attr = value value = obj.db.attr
|
||||
|
||||
And for storing something non-persistently (stored only until the server
|
||||
reboots) you can just do
|
||||
|
||||
::
|
||||
|
||||
obj.attr = value value = obj.attr
|
||||
|
||||
The last example may sound trivial, but it's actually impossible to do
|
||||
in trunk since django objects are not guaranteed to remain the same
|
||||
between calls (only stuff stored to the database is guaranteed to
|
||||
remain). Devel makes use of the third-party ``idmapper`` functionality
|
||||
to offer this functionality. This used to be a very confusing thing to
|
||||
new Evennia admins.
|
||||
|
||||
*All* database fields in Devel are now accessed through properties that
|
||||
handle in/out data storage. There is no need to save() explicitly
|
||||
anymore; indeed you should ideally not need to know the actual Field
|
||||
names.
|
||||
|
||||
Always full persistence -> Semi/Full persistence
|
||||
------------------------------------------------
|
||||
|
||||
In Evennia trunk, everything has to be saved back/from the database at
|
||||
all times, also if you just need a temporary storage that you'll use
|
||||
only once, one second from now. This enforced full persistency is a good
|
||||
thing for most cases - especially for web-integration, where you want
|
||||
the world to be consistent regardless of from where you are accessing
|
||||
it. Devel offer the ability to yourself decide this; since
|
||||
semi-persistent variables can be stored on objects (see previous
|
||||
section). What actually happens is that such variables are stored on a
|
||||
normal python object called ``ndb`` (non-database), which is
|
||||
transparently accessed. This does not touch the database at all.
|
||||
|
||||
Evennia-devel offers a setting ``FULL_PERSISTENCE`` that switches how
|
||||
the server operates. With this off, you have to explicitly assign
|
||||
attributes to database storage with e.g. ``obj.db.attr = value``,
|
||||
whereas normal assignment (``obj.attr = value``) will be stored
|
||||
non-persistent. With ``FULL_PERSISTENT`` on however, the roles are
|
||||
reversed. Doing ``obj.attr = value`` will now actually be saving to
|
||||
database, and you have to explicitly do ``obj.ndb.attr = value`` if you
|
||||
want non-persistence. In the end it's a matter of taste and of what kind
|
||||
of game/features you are implementing. Default is to use full
|
||||
persistence (but all of the engine explicitly put out ``db`` and ``ndb``
|
||||
making it work the same with both).
|
||||
|
||||
Commonly used functions/concept that changed names
|
||||
==================================================
|
||||
|
||||
There used to be that sending data to a player object used a method
|
||||
``emit_to()``, whereas sending data to a session used a method
|
||||
``msg()``. Both are now called ``msg()``. Since there are situations
|
||||
where it might be unclear if you receive a session or a player object
|
||||
(especially during login/logout), you can now use simply use ``msg()``
|
||||
without having to check (however, you *can* still use ``emit_to`` for
|
||||
legacy code, it's an alias to msg() now). Same is true with
|
||||
emit*to*contents() -> msg*to*contents().
|
||||
|
||||
``source_object`` in default commands are now consistently named
|
||||
*caller* instead.
|
||||
|
||||
``obj.get_attribute_value(attr)`` is now just
|
||||
``obj.get_attribute(attr)`` (but see the section on Attributes above,
|
||||
you should just use ``obj.db.attr`` to access your attribute).
|
||||
|
||||
How hard is it to convert from trunk to devel?
|
||||
==============================================
|
||||
|
||||
It depends. Any game logic game modules you have written (AI codes,
|
||||
whatever) should ideally not do much more than take input/output from
|
||||
evennia. These can usually be used straight off.
|
||||
|
||||
Commands and Script parents take more work but translate over quite
|
||||
cleanly since the idea is the same. For commands, you need to make the
|
||||
function into a class and add the parse(self) and func(self) methods
|
||||
(parse should be moved into a parent class so you don't have to use as
|
||||
much double code), as well as learn what variable names is made
|
||||
available (see the commands in ``gamesrc/commands/default`` for
|
||||
guidance). You can make States into CmdSets very easy - just listing the
|
||||
commands needed for the state in a new !CmdSet.
|
||||
|
||||
Script parents are made into Typeclasses by deleting the factory
|
||||
function and making them inherit from a TypeClassed object (such as
|
||||
Object or Player) like the ones in ``gamesrc/typeclasses/basetypes.py``,
|
||||
and then removing all code explicitly dealing with script parents.
|
||||
|
||||
Converting to the new Scripts (again, don't confuse with the old *script
|
||||
parents*!) is probably the trickiest, since they are a more powerful
|
||||
incarnation of what used to be two separate things; States and Events.
|
||||
See the examples in the ``gamesrc/scripts/`` for some ideas.
|
||||
|
||||
Better docs on all of this will be forthcoming.
|
||||
|
||||
Things not working/not implemented in devel (Aug 2010)
|
||||
======================================================
|
||||
|
||||
All features planned to go into Devel are finished. There are a few
|
||||
features available in Trunk that is not going to work in Devel until
|
||||
after it merges with Trunk:
|
||||
|
||||
- IMC2/IRC support is not implemented.
|
||||
- Attribute-level permissions are not formalized in the default cmdset.
|
||||
- Some of the more esoteric commands are not converted.
|
||||
|
||||
Please play with it and report bugs to our bug tracker!
|
||||
139
docs/sphinx/source/wiki/EvenniaIntroduction.rst
Normal file
139
docs/sphinx/source/wiki/EvenniaIntroduction.rst
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
"*A MUD (originally Multi-User Dungeon, with later variants Multi-User
|
||||
Dimension and Multi-User Domain), pronounced /ˈmʌd/, is a multiplayer
|
||||
real-time virtual world described primarily in text. MUDs combine
|
||||
elements of role-playing games, hack and slash, player versus player,
|
||||
interactive fiction, and online chat. Players can read or view
|
||||
descriptions of rooms, objects, other players, non-player characters,
|
||||
and actions performed in the virtual world. Players typically interact
|
||||
with each other and the world by typing commands that resemble a natural
|
||||
language.*" - `Wikipedia <http://en.wikipedia.org/wiki/MUD>`_
|
||||
|
||||
Evennia introduction
|
||||
====================
|
||||
|
||||
If you are reading this, it's quite likely you are dreaming of creating
|
||||
and running a text-based massively-multiplayer game
|
||||
(`MUD/MUX/MU <http://en.wikipedia.org/wiki/Mu%3Cstrong%3E>`_ etc) of
|
||||
your very own. You might just be starting to think about it, or you
|
||||
might have lugged around that *perfect* game in your mind for years ...
|
||||
you know *just* how good it would be, if you could only make it come to
|
||||
reality. We know how you feel. That is, after all why Evennia came to
|
||||
be.
|
||||
|
||||
Evennia is in principle a MUD-building system: a bare-bones Python
|
||||
codebase and server intended to be highly extendable for any style of
|
||||
game. "Bare-bones" in this context means that we try to impose as few
|
||||
game-specific things on you as possible. So whereas we for convenience
|
||||
offer basic building blocks like objects, characters, rooms, default
|
||||
commands for building and administration etc, we don't prescribe any
|
||||
combat rules, mob AI, races, skills, character classes or other things
|
||||
that will be different from game to game anyway. It is possible that we
|
||||
will offer some such systems as contributions in the future, but these
|
||||
will in that case all be optional.
|
||||
|
||||
What we *do* however, is to provide a solid foundation for all the
|
||||
boring database, networking, and behind-the-scenes administration stuff
|
||||
that all online games need whether they like it or not. Evennia is by
|
||||
default *fully persistent*, that means things you drop on the ground
|
||||
somewhere will still be there a dozen server reboots later. Through
|
||||
Django, we support a large variety of different database systems (the
|
||||
default of which is created for you automatically).
|
||||
|
||||
Using the full power of Python throughout the server offers some
|
||||
distinct advantages. All your coding, from object definitions and custom
|
||||
commands to AI scripts and economic systems are done in normal Python
|
||||
modules rather than some ad-hoc scripting language. The fact that you
|
||||
script the game in the same high-level language that you code it in
|
||||
allows for very powerful and custom game implementations indeed.
|
||||
|
||||
The server ships with a default set of player commands that are similar
|
||||
to the MUX command set. We *do not* aim specifically to be a MUX server,
|
||||
but we had to pick some default to go with (see `this <SoftCode.html>`_
|
||||
for more about our original motivations). It's easy to remove or add
|
||||
commands, or to have the command syntax mimic other systems, like Diku,
|
||||
LP, MOO and so on. Or why not create a new and better command system of
|
||||
your own design.
|
||||
|
||||
There is already a default django website as well as an ajax web client
|
||||
shipping with Evennia. You can also edit the database from the browser
|
||||
using the admin interface. Apart from telnet, SSH, SSL and web
|
||||
connections, you can connect e.g. IRC and IMC2 channels to evennia's
|
||||
in-game channels so that your players can chat with people "outside" the
|
||||
game. If you didn't see it before, there is a
|
||||
`screenshot <Screenshot.html>`_ of Evennia running that shows some of
|
||||
the connections in action.
|
||||
|
||||
What you need to know to work with Evennia
|
||||
==========================================
|
||||
|
||||
Assuming you have Evennia working (see the `quick start
|
||||
instructions <GettingStarted.html>`_) and have gotten as far as to start
|
||||
the server and connect to it with the client of your choice, here's what
|
||||
you need to know depending on your skills and needs.
|
||||
|
||||
I don't know (or don't want to do) any programming - I just want to run
|
||||
a game!
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Evennia comes with a default set of commands for the Python newbies and
|
||||
for those who need to get a game running *now*. Stock Evennia is enough
|
||||
for running a simple 'Talker'-type game - you can build and describe
|
||||
rooms and basic objects, have chat channels, do emotes and other things
|
||||
suitable for a social or free-form MU``*``. Combat, mobs and other game
|
||||
elements are not included, so you'll have a very basic game indeed if
|
||||
you are not willing to do at least *some* coding.
|
||||
|
||||
I know basic Python, or am willing to learn
|
||||
-------------------------------------------
|
||||
|
||||
Evennia's source code is extensively documented and `viewable
|
||||
online <http://code.google.com/p/evennia/source/browse/trunk>`_. We also
|
||||
have a comprehensive `online
|
||||
manual <http://code.google.com/p/evennia/wiki/Index>`_ with lots of
|
||||
examples. But while Python is a relatively easy programming language, it
|
||||
still represents a learning curve if you are new to programming. You
|
||||
should probably sit down with a Python beginner's
|
||||
`tutorial <http://docs.python.org/tutorial/tutorial>`_ (there are plenty
|
||||
of them on the web if you look around) so you at least know know what
|
||||
you are seeing. To efficiently code your dream game in Evennia you don't
|
||||
need to be a Python guru, but you do need to be able to read example
|
||||
code containing at least these basic Python features:
|
||||
|
||||
- Importing python modules
|
||||
- Using variables, `conditional
|
||||
statements <http://docs.python.org/tutorial/controlflow.html#if-statements>`_,
|
||||
`loops <http://docs.python.org/tutorial/controlflow.html#for-statements>`_
|
||||
and
|
||||
`functions <http://docs.python.org/tutorial/controlflow.html#defining-functions>`_
|
||||
- Using `lists, dictionaries and list
|
||||
comprehensions <http://docs.python.org/tutorial/datastructures.html>`_
|
||||
- Doing `string handling and
|
||||
formatting <http://docs.python.org/tutorial/introduction.html#strings>`_
|
||||
- Using `Classes <http://docs.python.org/tutorial/classes.html>`_,
|
||||
their methods and properties
|
||||
|
||||
Obviously, the more things you feel comfortable with, the easier time
|
||||
you'll have to find your way. With just basic knowledge you should be
|
||||
able to define your own `Commands <Commands.html>`_, create custom
|
||||
`Objects <Objects.html>`_ as well as make your world come alive with
|
||||
basic `Scripts <Scripts.html>`_. You can definitely build a whole
|
||||
advanced and customized game from extending Evennia's examples only.
|
||||
|
||||
I know my Python stuff and am willing to use it!
|
||||
------------------------------------------------
|
||||
|
||||
Even if you started out as a Python beginner, you will likely get to
|
||||
this point after working on your game for a while. With more general
|
||||
knowledge in Python the full power of Evennia opens up for you. Apart
|
||||
from modifying commands, objects and scripts, you can develop everything
|
||||
from advanced mob AI and economic systems, through sophisticated combat
|
||||
and social minigames, to redefining how commands, players, rooms or
|
||||
channels themselves work. Since you code your game by importing normal
|
||||
Python modules, there are few limits to what you can accomplish.
|
||||
|
||||
If you *also* happen to know some web programming (HTML, CSS,
|
||||
Javascript) there is also a web presence (a website and an mud web
|
||||
client) to play around with ...
|
||||
|
||||
From here you can continue to the `Index <Index.html>`_ to find more
|
||||
info about Evennia.
|
||||
137
docs/sphinx/source/wiki/ExecutePythonCode.rst
Normal file
137
docs/sphinx/source/wiki/ExecutePythonCode.rst
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
<wiki:toc max\_depth
|
||||
|
||||
"3" />
|
||||
======
|
||||
|
||||
The ``@py`` command =
|
||||
|
||||
The ``@py`` command supplied with the default command set of Evennia
|
||||
allows you to execute Python commands directly from inside the game. An
|
||||
alias to ``@py`` is simply "``!``". *Access to the ``@py`` command
|
||||
should be severely restricted only to game admins.* Being able to
|
||||
execute arbitrary Python code on the server is not something you should
|
||||
entrust to just anybody.
|
||||
|
||||
::
|
||||
|
||||
@py 1+2 <<< 3
|
||||
|
||||
Available variables
|
||||
-------------------
|
||||
|
||||
A few local variables are made available when running ``@py``. These
|
||||
offer entry into the running system and allows for quick exploration of
|
||||
the standard objects.
|
||||
|
||||
- **self** / **me** - the calling object (i.e. you)
|
||||
- **here** - the current caller's location
|
||||
- **obj** - a dummy `Object <Objects.html>`_ instance
|
||||
- **script** - a dummy `Script <Scripts.html>`_ instance
|
||||
- **config** - a dummy ConfigValue instance
|
||||
- **ObjectDB** - direct reference to the ObjectDB database class
|
||||
- **ScriptDB** - direct reference to the ScriptDB database class
|
||||
- **!ConfigValue** - direct reference to the ConfigValue database class
|
||||
|
||||
Returning output
|
||||
----------------
|
||||
|
||||
This is an example where we import and test one of Evennia's utilities
|
||||
found in ``src/utils/utils.py``:
|
||||
|
||||
::
|
||||
|
||||
@py from src.utils import utils; utils.time_format(33333) <<< Done.
|
||||
|
||||
Note that we didn't get any return value, all we where told is that the
|
||||
code finished executing without error. This is often the case in more
|
||||
complex pieces of code which has no single obvious return value. To see
|
||||
the output from the ``time_format()`` function we need to tell the
|
||||
system to echo it to us explicitly with ``self.msg()``.
|
||||
|
||||
::
|
||||
|
||||
@py from src.utils import utils; self.msg(utils.time_format(33333)) 09:15 <<< Done.
|
||||
|
||||
If you were to use Python's standard ``print``, you will see the result
|
||||
in your current ``stdout`` (your terminal by default), *if* you are
|
||||
running Evennia in *interactive mode* (with the ``-i`` flag).
|
||||
|
||||
Finding objects
|
||||
---------------
|
||||
|
||||
A common use for ``@py`` is to explore objects in the database, for
|
||||
debugging and performing specific operations that are not covered by a
|
||||
particular command.
|
||||
|
||||
Locating an object is best done using ``self.search()``:
|
||||
|
||||
::
|
||||
|
||||
@py self.search("red_ball") <<< Ball @py self.search("red_ball").db.color = "red" <<< Done. @py self.search("red_ball").db.color <<< red
|
||||
|
||||
``self.search()`` is by far the most used case, but you can also search
|
||||
other database tables for other Evennia entities like scripts or
|
||||
configuration entities. To do this you can use the generic search
|
||||
entries found in ``src.utils.search``.
|
||||
|
||||
::
|
||||
|
||||
@py from src.utils import search; self.msg(search.scripts("sys_game_time")) <<< [<src.utils.gametime.GameTime object at 0x852be2c>]
|
||||
|
||||
You can also use the database model managers directly (accessible
|
||||
through the ``objects`` properties of database models). This is a bit
|
||||
more flexible since it gives you access to the full range of database
|
||||
search methods defined in each manager.
|
||||
|
||||
::
|
||||
|
||||
@py ScriptDB.objects.script_search("sys_game_time") <<< [<src.utils.gametime.GameTime object at 0x852be2c>]
|
||||
|
||||
(Note that since this second example becomes a simple statement, we
|
||||
don't have to wrap it in ``self.msg()`` to get the output). If you want
|
||||
to see what is available, the managers are found in the ``manager.py``
|
||||
files throughout the ``src`` directory (e.g.
|
||||
``src/objects/manager.py``). Through the manager you can also view the
|
||||
contents of the database using normal Django query operations:
|
||||
|
||||
::
|
||||
|
||||
@py ConfigValue.objects.all() <<< [<ConfigValue: default_home]>, <ConfigValue:site_name>, ...]
|
||||
|
||||
In doing so however, keep in mind the difference between `Typeclasses
|
||||
and Database Objects <Typeclasses.html>`_: Using the search commands in
|
||||
the managers will return *!TypeClasses*. Using Django's default search
|
||||
methods (``get``, ``filter`` etc) will return *Database objects*. This
|
||||
distinction can often be disregarded, but as a convention you should try
|
||||
to stick with the manager search functions and work with TypeClasses in
|
||||
most situations.
|
||||
|
||||
::
|
||||
|
||||
# this uses Evennia's manager method get_id(). # It returns a Character typeclass instance @py ObjectDB.objects.get_id(1).__class__ <<< Character# this uses the standard Django get() query. # It returns a django database model instance. @py ObjectDB.objects.get(id=1).__class__ <<< <class 'src.objects.models.ObjectDB'>
|
||||
|
||||
Running a Python Parser outside the game
|
||||
========================================
|
||||
|
||||
``@py`` has the advantage of operating inside a running server, where
|
||||
you can test things in real time. Much of this *can* be done from the
|
||||
outside too though.
|
||||
|
||||
Go to the ``game`` directory and get into a new terminal.
|
||||
|
||||
::
|
||||
|
||||
python manage.py shell
|
||||
|
||||
Your default Python intrepeter will start up, configured to be able to
|
||||
work with and import all modules of your Evennia installation. From here
|
||||
you can explore the database and test-run individual modules as desired.
|
||||
Not only does a fully featured Python interpreter like
|
||||
`iPython <http://ipython.scipy.org/moin/>`_ allow you to work over
|
||||
several lines, it also has lots of other editing features, usch as
|
||||
tab-completion and ``__doc__``-string reading.
|
||||
|
||||
::
|
||||
|
||||
$ python manage.py shellIPython 0.10 -- An enhanced Interactive Python ...In [1]: from src.objects.models import ObjectDB In [2]: ObjectDB.objects.all() Out[3]: [<ObjectDB: Harry>, <ObjectDB: Limbo>, ...]
|
||||
|
||||
313
docs/sphinx/source/wiki/GettingStarted.rst
Normal file
313
docs/sphinx/source/wiki/GettingStarted.rst
Normal file
|
|
@ -0,0 +1,313 @@
|
|||
Getting Started
|
||||
===============
|
||||
|
||||
This will help you download, install and start Evennia for the first
|
||||
time.
|
||||
|
||||
Quick start
|
||||
-----------
|
||||
|
||||
For you who are extremely impatient, here's the gist of getting a
|
||||
vanilla Evennia install running.
|
||||
|
||||
#. *Get the pre-requisites (mainly Python, Django, Twisted and
|
||||
Mercurial)*.
|
||||
#. *Start a command terminal/dos prompt and change directory to where
|
||||
you want to have your 'evennia' folder appear*.
|
||||
#. ``hg clone https://code.google.com/p/evennia/ evennia``
|
||||
#. *Change directory to evennia/game*.
|
||||
#. ``python manage.py``
|
||||
#. ``python manage.py syncdb``
|
||||
#. ``python evennia.py -i start``
|
||||
|
||||
Evennia should now be running and you can connect to it by pointing a
|
||||
web browser to ``http://localhost:8000`` or a MUD telnet client to
|
||||
``localhost:4000``.
|
||||
|
||||
Read on for more detailed instructions and configurations.
|
||||
|
||||
Pre-Requesites
|
||||
--------------
|
||||
|
||||
As far as operating systems go, any system with Python support should
|
||||
work.
|
||||
|
||||
- Linux/Unix
|
||||
- Windows (2000, XP, Vista, Win7)
|
||||
- Mac OSX (>=10.5 recommended)
|
||||
|
||||
If you run into problems, or have success running Evennia on another
|
||||
platform, please let us know.
|
||||
|
||||
You'll need the following packages and minimum versions in order to run
|
||||
Evennia:
|
||||
|
||||
**Python** (http://www.python.org)
|
||||
|
||||
- Version 2.5+ strongly recommended, although 2.3 or 2.4 **may** work.
|
||||
Obs- Python3.x is not supported yet.
|
||||
- The default database system SQLite3 only comes as part of Python2.5
|
||||
and later.
|
||||
- Python is available in all modern operating systems (Linux, Mac,
|
||||
etc).
|
||||
- Windows users are recommended to use ActivePython
|
||||
(http://www.activestate.com/activepython)
|
||||
|
||||
**Twisted** (http://twistedmatrix.com)
|
||||
|
||||
Version 10.0+
|
||||
|
||||
Twisted also requires:
|
||||
|
||||
- !ZopeInterface 3.0+ (http://www.zope.org/Products/ZopeInterface)
|
||||
- For Windows only: pywin32 (http://sourceforge.net/projects/pywin32)
|
||||
|
||||
**Django** (http://www.djangoproject.com)
|
||||
|
||||
- Version 1.2.1+ or latest subversion trunk highly recommended.
|
||||
- PIL library (http://www.pythonware.com/products/pil)
|
||||
|
||||
To download/update Evennia:
|
||||
|
||||
**Mercurial** (http://mercurial.selenic.com/)
|
||||
|
||||
- This is needed to download and update Evennia itself.
|
||||
|
||||
Optional packages:
|
||||
|
||||
**South** (http://south.aeracode.org/)
|
||||
|
||||
- Version 0.7+
|
||||
- Optional. Used for database migrations.
|
||||
|
||||
**Apache2** (http://httpd.apache.org)
|
||||
|
||||
- Optional. Most likely you'll not need to bother with this since
|
||||
Evennia runs its own threaded web server based on Twisted. Other
|
||||
equivalent web servers with a Python interpreter module can also be
|
||||
used.
|
||||
|
||||
*Note: You don't need to make anything visible to the 'net in order to
|
||||
run and test out Evennia. Apart from downloading/updating Evennia itself
|
||||
you don't even need to have an internet connection. Of course you'll
|
||||
probably want that as your game matures, but until then it works nicely
|
||||
to develop and play around completely in the sanctity and isolation of
|
||||
your local machine.*
|
||||
|
||||
Installing pre-requisites
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
**Linux** package managers should usually handle all this for you.
|
||||
Python itself is definitely available through all distributions. On
|
||||
Debian-derived systems you can do something like this (as root) to get
|
||||
all you need:
|
||||
|
||||
``apt-get install python python-django python-twisted mercurial``
|
||||
|
||||
If some or all dependencies are not readily available (for example,
|
||||
running some flavors of !RedHat/CentOS or an older Debian version) you
|
||||
can still retrieve them easily by using Python's
|
||||
`easyinstall <http://packages.python.org/distribute/easy%3Ci%3Einstall.html>`_
|
||||
or the alternative
|
||||
`pip <http://www.pip-installer.org/en/latest/index.html>`_:
|
||||
``easy_install django twisted pil mercurial``
|
||||
|
||||
``pip install django twisted pil mercurial``
|
||||
|
||||
**Windows** users may choose to install
|
||||
`ActivePython <http://www.activestate.com/activepython>`_ instead of the
|
||||
usual Python. If ActivePython is installed, you can use
|
||||
`pypm <http://docs.activestate.com/activepython/2.6/pypm.html>`_ in the
|
||||
same manner as ``easy_install``/``pip`` above. This *greatly* simplifies
|
||||
getting started on Windows:
|
||||
|
||||
``pypm install Django Twisted PIL Mercurial``
|
||||
|
||||
Another simple alternative (for all platforms) is to set up a *virtual
|
||||
Python environment* and install to that. This is covered
|
||||
`here <GettingStarted#Optional:%3Ci%3EA%3C/i%3Eseparate%3Ci%3Einstallation%3C/i%3Eenvironment%3Ci%3Ewith%3C/i%3Evirtualenv.html>`_.
|
||||
|
||||
Windows users not using ActivePython or virtual environments will have
|
||||
to manually download and install the packages in turn - most have normal
|
||||
Windows installers, but in some cases you'll need to know how to use the
|
||||
Windows command prompt to execute some python install scripts.
|
||||
|
||||
Step 1: Obtaining the Server
|
||||
----------------------------
|
||||
|
||||
To download Evennia you need the Mercurial client to grab a copy of the
|
||||
source.
|
||||
|
||||
For command-line Mercurial client users, something like this will do the
|
||||
trick (first place yourself in a directory where you want a new folder
|
||||
``evennia`` to be created):
|
||||
|
||||
``hg clone https://code.google.com/p/evennia/ evennia``
|
||||
|
||||
(``hg`` is the chemical abbreviation of mercury, hence the use of ``hg``
|
||||
for ``mercurial``)
|
||||
|
||||
In the future, you just do
|
||||
|
||||
``hg pull``
|
||||
|
||||
from your ``evennia/`` directory to obtain the latest updates.
|
||||
|
||||
If you use a graphical Mercurial client, use the equivalent buttons to
|
||||
perform the above operations.
|
||||
|
||||
Step 2: Setting up the Server
|
||||
-----------------------------
|
||||
|
||||
From within the Evennia ``game`` directory (``evennia/game/``, if you
|
||||
followed the Subversion instructions above) type the following to
|
||||
trigger the automatic creation of an empty ``settings.py`` file.
|
||||
|
||||
``python manage.py``
|
||||
|
||||
Your new ``settings.py`` file will just be an empty template initially.
|
||||
In ``evennia/src/settings_default.py`` you will find the settings that
|
||||
may be copied/pasted into your ``settings.py`` to override the defaults.
|
||||
This will be the case if you want to adjust paths or use something other
|
||||
than the default SQLite3 database engine. You *never* want to modify
|
||||
``settings_default.py`` directly - as the server is developed, this file
|
||||
might be overwritten with new versions and features.
|
||||
|
||||
If you would like to use something other than the default SQLite setup
|
||||
(which works "out of the box"), you'll need to copy the ``DATABASE_*``
|
||||
variables from ``settings_defaults.py`` and paste them to
|
||||
``settings.py``, making your modifications there.
|
||||
|
||||
*Note that the settings.py file is in fact a normal python module which
|
||||
imports the default settings. This means that all variables have been
|
||||
set to default values by the time you get to change things. So to
|
||||
customize a particular variable you have to copy&paste it to your
|
||||
settings file - and you have to do so also for variables that depend on
|
||||
that variable (if any), or the dependent variables will remain at the
|
||||
default values.*
|
||||
|
||||
Finally, enter the following command in a terminal or shell to create
|
||||
the database file (in the case of SQLite) and populate the database with
|
||||
the standard tables and values:
|
||||
|
||||
``python manage.py syncdb``
|
||||
|
||||
You should be asked for a superuser username, email, and password. Make
|
||||
**sure** you create a superuser here when asked, this becomes your login
|
||||
name for the superuser account ``#1`` in game. After this you will see a
|
||||
lot of spammy install messages. If all goes well, you're ready to
|
||||
continue to the next step. If not, look at the error messages and
|
||||
double-check your ``settings.py`` file.
|
||||
|
||||
If you installed ``South`` for database schema migrations, you will then
|
||||
need to do this:
|
||||
|
||||
``python manage.py migrate``
|
||||
|
||||
This will migrate the server to the latest version. If you don't use
|
||||
``South``, migrations will not be used and your server will already be
|
||||
at the latest version (but your existing database might have to be
|
||||
manually edited to match future server changes).
|
||||
|
||||
Step 3: Starting and Stopping the Server
|
||||
----------------------------------------
|
||||
|
||||
To start the server, make sure you're in the ``evennia/game`` directory
|
||||
and execute ``evennia.py`` like this:
|
||||
|
||||
``python evennia.py -i start``
|
||||
|
||||
This starts the server and portal. The ``-i`` flag means that the server
|
||||
starts in *interactive mode*, as a foreground process. You will see
|
||||
debug/log messages directly in the terminal window instead of logging
|
||||
them to a file.
|
||||
|
||||
Running the server in interactive mode is very useful for development
|
||||
and debugging but is not recommended for production environments. For
|
||||
the latter you'll want to run it as a *daemon* by skipping the ``-i``
|
||||
flag:
|
||||
|
||||
``python evennia.py start``
|
||||
|
||||
This will start the server as a background process. Server messages will
|
||||
be logged to a file you specify in your configuration file (default is a
|
||||
file in ``game/logs``).
|
||||
|
||||
To stop Evennia, do:
|
||||
|
||||
``python evennia.py stop``
|
||||
|
||||
Step 4: Connecting to the server
|
||||
--------------------------------
|
||||
|
||||
The Evennia server is now up and running. You should now be able to
|
||||
login with any mud client or telnet client using the email address and
|
||||
password you specified when syncing the database. If you are just
|
||||
testing the server out on your local machine, the server name will most
|
||||
likely be ``localhost`` whereas the port used by default is ``4000``.
|
||||
|
||||
If the defaults are not changed, Evennia will also start its own
|
||||
Twisted-based web server on port 8000. Point your web browser to
|
||||
``http://localhost:8000/``. The *admin interface* allows you to edit the
|
||||
game database online and you can connect directly to the game by use of
|
||||
the ajax web client.
|
||||
|
||||
Welcome to Evennia! Why not try `building
|
||||
something <BuildingQuickstart.html>`_ next?
|
||||
|
||||
Optional: Database migrations with South
|
||||
========================================
|
||||
|
||||
Evennia supports database migrations using
|
||||
`South <http://south.aeracode.org/>`_, a Django database schema
|
||||
migration tool. Installing South is optional, but if it is installed,
|
||||
Evennia *will* use it automatically, meaning this section comes into
|
||||
play. You can install South from
|
||||
`http://south.aeracode.org/. <http://south.aeracode.org/.>`_ It is also
|
||||
available through the normal package distributions, easy\_install, pip,
|
||||
or pypm (see above notes).
|
||||
|
||||
Whenever you see a commit or mailing list message instructing you to run
|
||||
migrations to update your DB schema, simply do the following from within
|
||||
the ``evennia/game`` directory: ``python manage.py migrate``
|
||||
|
||||
You should see migrations being applied, and should be left with an
|
||||
updated DB schema afterwards.
|
||||
|
||||
Optional: A separate installation environment with virtualenv
|
||||
=============================================================
|
||||
|
||||
Apart from installing the packages and versions as above, you can also
|
||||
set up a very fast self-contained Evennia install using the
|
||||
`virtualenv <http://pypi.python.org/pypi/virtualenv>`_ program.
|
||||
Virtualenv sets aside a folder on your harddrive as a stand-alone Python
|
||||
environment. It should work both on Linux and Windows. First, install
|
||||
Python as normal, then get virtualenv and install it so you can run it
|
||||
from the command line. This is an example for setting up Evennia in an
|
||||
isolated new folder *mudenv*:
|
||||
|
||||
::
|
||||
|
||||
python virtualenv mudenv --no-site-packages cd mudenv
|
||||
|
||||
Now we should be in our new directory *mudenv*. Next we activate the
|
||||
virtual environment in here.
|
||||
|
||||
::
|
||||
|
||||
# for Linux: source bin/activate # for Windows: <path_to_this_place>\bin\activate.bat
|
||||
|
||||
In here you can play around and install python packages of any version
|
||||
without affecting your normal system installation at all. Next we get
|
||||
all the requirements with *pip*, which comes with virtualenv. This is
|
||||
the cool bit.
|
||||
|
||||
::
|
||||
|
||||
pip install django twisted pil
|
||||
|
||||
You can now refer to **Step 1** above and continue on from there to
|
||||
install Evennia into *mudenv* (you need to get ``subversion`` manually
|
||||
still, it's not a python program). In the future, just go into the
|
||||
folder and activate it to make this separate virtual environment
|
||||
available to Evennia.
|
||||
114
docs/sphinx/source/wiki/HelpSystem.rst
Normal file
114
docs/sphinx/source/wiki/HelpSystem.rst
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
*How to use Evennia's help system*
|
||||
|
||||
Help system
|
||||
===========
|
||||
|
||||
An important part of Evennia is the online help system. This allows the
|
||||
players and staff alike to learn how to use the game's commands as well
|
||||
as other information pertinent to the game. The help system has many
|
||||
different aspects, from the normal editing of help entries from inside
|
||||
the game, to auto-generated help entries during code development using
|
||||
the *auto-help* system.
|
||||
|
||||
Viewing the help database
|
||||
-------------------------
|
||||
|
||||
The main command is ``help``.
|
||||
|
||||
::
|
||||
|
||||
help [searchstring]
|
||||
|
||||
This will show a list of help entries, ordered after categories. You
|
||||
will find two sections, *Command help entries* and *Other help entries*
|
||||
(initially you will only have the first one). You can use help to get
|
||||
more info about an entry; you can also give partial matches to get
|
||||
suggestions. If you give category names you will only be shown the
|
||||
topics in that category.
|
||||
|
||||
Command Auto-help system
|
||||
------------------------
|
||||
|
||||
One important use of the help system is to teach the use of in-game
|
||||
commands. Evennia offers a dynamically updated help system for all your
|
||||
commands, new and old, known simply as the *auto-help* system. Only
|
||||
commands that you can actually use are picked up by the auto-help
|
||||
system. That means an admin will see a considerably larger mass of help
|
||||
topics when using the ``help`` command than a normal player.
|
||||
|
||||
The auto-help system uses the ``__doc__`` strings of your command
|
||||
definitions and formats this to a nice-looking help entry. This makes
|
||||
for a very easy way to keep the help updated - just document your
|
||||
commands well - updating the help system is just a ``@reload`` away.
|
||||
There is no need to manually create help database entries for commands;
|
||||
as long as you keep the docstrings updated your help will be dynamically
|
||||
updated for you as well.
|
||||
|
||||
Example (from a module with command definitions):
|
||||
|
||||
::
|
||||
|
||||
class CmdMyCmd(Command): """ mycmd - my very own command Usage: mycmd[/switches] <args> Switches: test - test the command run - do something else This is my own command that does things to you when you supply it with arguments. """ ... help_category = "Building" ...
|
||||
|
||||
So the text at the very top of the command class definition is the
|
||||
class' ``__doc__``-string and what will be shown to users looking for
|
||||
help. Try to use a consistent formatting between your help strings (for
|
||||
example, all default commands have ``__doc__``-strings formatted in the
|
||||
way seen above). You should also supply the ``help_category`` class
|
||||
property if you can; this helps to group help entries together for
|
||||
easier finding (if you don't supply a help\_category, "General" will be
|
||||
assumed).
|
||||
|
||||
Other help entries (entries stored in database)
|
||||
-----------------------------------------------
|
||||
|
||||
The *Other help* section you see when using the ``help`` command shows
|
||||
all help entries that has been manually added to the database by staff.
|
||||
Instead of being generated from the code by Evennia, these are stored in
|
||||
the database using a model called *!HelpEntry*. HelpEntry topics are
|
||||
intended for world-game-info, tutorials and other types of useful
|
||||
information not directly tied to a command and covered by auto-help.
|
||||
|
||||
A help entry consists of four parts:
|
||||
|
||||
- The *topic*. This is the name of the help entry. This is what players
|
||||
search for when they are looking for help. The topic can contain
|
||||
spaces.
|
||||
- The *help category*. Examples are *Administration*, *Building*,
|
||||
*Comms* or *General*. This is an overall grouping of similar help
|
||||
topics, used by the engine to give a better overview.
|
||||
- The *text* - the help text itself, of any length. This can also
|
||||
include *markup*, see below.
|
||||
- locks - a `lock definition <Locks.html>`_. Help commands check for
|
||||
access\_types ``examine`` and ``edit``.
|
||||
|
||||
You can create new help entries in code by using
|
||||
``src.utils.create.create_help_entry()``:
|
||||
|
||||
::
|
||||
|
||||
from src.utils import create entry = create.create_help_entry("emote", "Emoting is important because ...", category="Roleplaying", locks="view:all()"):
|
||||
|
||||
From inside the game those with the right permissions can use the
|
||||
``@sethelp`` command to add and modify help entries.
|
||||
|
||||
::
|
||||
|
||||
> @sethelp/add emote = The emote command is ...
|
||||
|
||||
Using ``@sethelp`` you can add, delete and append text to existing
|
||||
entries. By default new entries will go in the *General* help category.
|
||||
You can change this using a different form of the ``@sethelp`` command:
|
||||
|
||||
::
|
||||
|
||||
> @sethelp/add emote, Roleplaying = Emoting is important because ...
|
||||
|
||||
If the category *Roleplaying* did not exist it is created and will
|
||||
appear in the help index. You can, finally, define a lock for the help
|
||||
entry by following the category with a `lock definition <Locks.html>`_:
|
||||
|
||||
::
|
||||
|
||||
> @sethelp/add emote, Roleplaying, view:all() = The emote command ...
|
||||
|
||||
61
docs/sphinx/source/wiki/HowToGetAndGiveHelp.rst
Normal file
61
docs/sphinx/source/wiki/HowToGetAndGiveHelp.rst
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
Getting and giving Evennia-help
|
||||
|
||||
How to *get* Help
|
||||
=================
|
||||
|
||||
If you cannot find what you are looking for in the `online
|
||||
documentation <Index.html>`_, here's what to do:
|
||||
|
||||
- If you have trouble with a missing feature or a problem you think is
|
||||
a bug, go to the `issue
|
||||
tracker <http://code.google.com/p/evennia/issues/list>`_. If you
|
||||
can't find the issue already reported, file a new one by filling in
|
||||
the handy form.
|
||||
- If you need help, want to start a discussion or get input on
|
||||
something, make a post in our `forum <http://evennia.com>`_. This is
|
||||
technically a 'mailing list', but you don't need to use e-mail; you
|
||||
can post and read all messages just as easily from your browser via
|
||||
the online interface.
|
||||
- If you want more direct discussions with developers and other users,
|
||||
consider dropping into our IRC chat channel
|
||||
"http://webchat.freenode.net/?channels
|
||||
evennia">#evennia on the *Freenode* network. Please note however that
|
||||
you have to be patient if you don't get any response immediately; we
|
||||
are all in very different time zones and many have busy personal
|
||||
lives. So you might have to lurk about for a while - you'll get
|
||||
noticed eventually!
|
||||
|
||||
How to *give* Help
|
||||
==================
|
||||
|
||||
Evennia is a completely non-funded project. It relies on the time
|
||||
donated by its users and developers in order to progress.
|
||||
|
||||
The first and easiest way you as a user can help us out is by taking
|
||||
part in `community
|
||||
discussions <http://groups.google.com/group/evennia/>`_ and by giving
|
||||
feedback on what is good or bad. Report bugs you find and features you
|
||||
lack to our `issue
|
||||
tracker <http://code.google.com/p/evennia/issues/list>`_. Just the
|
||||
simple act of letting developers know you are out there using their
|
||||
program is worth a lot.
|
||||
|
||||
If you'd like to help develop Evennia more hands-on, here are some ways
|
||||
to get going:
|
||||
|
||||
- Look through our `online documentation wiki <Index.html>`_ and see if
|
||||
you can help improve or expand the documentation (even small things
|
||||
like fixing typos!).
|
||||
- Send a message to our
|
||||
`forum <http://groups.google.com/group/evennia/>`_ and/or our
|
||||
"http://webchat.freenode.net/?channels
|
||||
evennia">IRC chat asking about what needs doing, along with what your
|
||||
interests and skills are.
|
||||
- Take a look at our `issue
|
||||
tracker <http://code.google.com/p/evennia/issues/list>`_ and see if
|
||||
there's something you feel like taking on.
|
||||
- Check out the `Contributing <Contributing.html>`_ page on how to
|
||||
contribute with code in practice.
|
||||
|
||||
In either case, you may find documentation useful to developers in the
|
||||
`Developer Central <DeveloperCentral.html>`_.
|
||||
123
docs/sphinx/source/wiki/IMC2.rst
Normal file
123
docs/sphinx/source/wiki/IMC2.rst
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
Introduction to and configuration for IMC2.
|
||||
|
||||
IMC2
|
||||
====
|
||||
|
||||
`IMC2 <http://en.wikipedia.org/wiki/InterMUD>`_, *!InterMud
|
||||
Communications, protocol version 2*, is a protocol that allows
|
||||
individual mud games (Evennia-powered or not) to connect to a remote
|
||||
server for the purpose of IRC-like communication with other games. By
|
||||
connecting your MUD to IMC, you and your admins/players will be able to
|
||||
communicate with players on other muds connected to the network! Note
|
||||
that you can use IMC2 also if your Evennia install is only running
|
||||
locally on your computer -all you need is an internet connection.
|
||||
|
||||
Evennia's IMC implementation is special in that it integrates Evennia's
|
||||
normal channel system with IMC. The basic principle is that you
|
||||
"connect" an IMC channel to an existing Evennia channel. Users on the
|
||||
IMC network will then see what is said on the channel and vice versa.
|
||||
|
||||
Joining the IMC network
|
||||
-----------------------
|
||||
|
||||
To configure IMC, you first need to activate it by setting
|
||||
``IMC2_ENABLED=True`` in your settings file. This will make several new
|
||||
IMC-related commands available to a privileged user. Since the IMC
|
||||
network will need to know your mud's name, make sure you have also set
|
||||
``settings.SERVERNAME`` to the mud name you want.
|
||||
|
||||
Next you need to register your mud at a IMC2 network. We suggest the
|
||||
`MudBytes IMC2 network <http://www.mudbytes.net/intermud>`_. You can
|
||||
join for free
|
||||
`here <http://www.mudbytes.net/imc2-intermud-join-network>`_. On that
|
||||
page, follow the following steps:
|
||||
|
||||
#. From the drop-down list, select "Other unsupported IMC2 version",
|
||||
then click Submit
|
||||
#. You will get to a form. In "Short Mud name" you need to enter the
|
||||
name of your mud as defined by ``settings.SERVERNAME``.
|
||||
#. Give client- and server passwords to anything you want, but remember
|
||||
them.
|
||||
#. Give an admin e-mail. This shouldn't be too critical.
|
||||
#. Choose a server. It shouldn't really matter which you choose, as long
|
||||
as you remember what you picked (Evennia's development channel
|
||||
``ievennia`` is found on ``Server01``). Click "Join".
|
||||
|
||||
You have now created an account on the Mudbytes IMC network and are
|
||||
ready to go on.
|
||||
|
||||
Now fill in the rest of the IMC2 information in your settings file -
|
||||
give the network name and port, as well as the client- and server
|
||||
passwords you used when registering on mudbytes.
|
||||
|
||||
For testing, you can connect your mud client to the IMC mini-mud called
|
||||
*Talon* on ``talon.mudbytes.net:2000``. This works pretty much like an
|
||||
IRC client.
|
||||
|
||||
Creating an Evennia channel
|
||||
---------------------------
|
||||
|
||||
Evennia maps in-game channels to remote IMC channels. This means that
|
||||
you get all of the features of the local comm system for remote IMC
|
||||
channels as well (channel history, permissions-based channel entry,
|
||||
etc.)
|
||||
|
||||
Let's create a dedicated Evennia channel to host imc communications (you
|
||||
could also use an existing channel like ``ooc`` if you wanted):
|
||||
|
||||
::
|
||||
|
||||
@ccreate imc2 = This is connected to an IMC2 channel!
|
||||
|
||||
You should join the channel automatically.
|
||||
|
||||
Setting up a Channel ``<->`` IMC2 binding
|
||||
-----------------------------------------
|
||||
|
||||
=
|
||||
|
||||
Evennia developers have an open-access IMC channel called ``ievennia``
|
||||
on ``Server01`` of the Mudbytes network. For Evennia development we
|
||||
recommend you connect to this for sharing evennia anecdotes!
|
||||
|
||||
Activating IMC2 have made new commands available, the one you need is
|
||||
``@imc2chan``. You use this to create a permanent link between an IMC
|
||||
channel and an existing Evennia channel of your choice. You can use the
|
||||
``imcchanlist`` to see which IMC channels are available on the network.
|
||||
|
||||
Let's connect our new ``imc2`` channel to the ``ievennia`` channel on
|
||||
Server01.
|
||||
|
||||
::
|
||||
|
||||
@imc2chan imc2 = ievennia
|
||||
|
||||
To test, use the IMC mud *Talon*, make sure you "listen" to
|
||||
``ievennia``, then write something to the channel. You should see the
|
||||
text appear in Evennia's ``imc2`` channel and vice versa.
|
||||
|
||||
Administration and notes
|
||||
------------------------
|
||||
|
||||
You can view all your IMC-to-Evennia mappings using ``@imc2chan/list``.
|
||||
To permanently remove a connection, use ``@imc2chan`` with the
|
||||
``/delete`` switch like this:
|
||||
|
||||
::
|
||||
|
||||
@imc2chan/delete imc2 = ievennia
|
||||
|
||||
A single Evennia channel may *listen* to any number of remote IMC
|
||||
channels. Just use ``@imc2chan`` to add more connections. Your channel
|
||||
can however only ever *send* to one IMC2 channel and that is the first
|
||||
one you link to it (``ievennia`` in this example).
|
||||
|
||||
The ``@imclist`` command will list all other MUDs connected to the
|
||||
network (not including yourself).
|
||||
|
||||
Talk between IRC and IMC
|
||||
------------------------
|
||||
|
||||
This is easy - just bind IMC to the same evennia channel that IRC binds
|
||||
to. The process of binding IRC channels is described in more detail
|
||||
`here <IRC.html>`_.
|
||||
115
docs/sphinx/source/wiki/IRC.rst
Normal file
115
docs/sphinx/source/wiki/IRC.rst
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
IRC
|
||||
===
|
||||
|
||||
`IRC (Internet Relay
|
||||
Chat) <http://en.wikipedia.org/wiki/Internet%3Ci%3ERelay%3C/i%3EChat>`_
|
||||
is a long standing chat protocol used by many open-source projects for
|
||||
communicating in real time. By connecting one of Evennia's
|
||||
`Channels <Communications.html>`_ to an IRC channel you can communicate
|
||||
also with people not on an mud themselves. Note that you can use IRC
|
||||
also if you are only running your Evennia MUD locally on your computer
|
||||
(your game don't need to be open to the public)! All you need is an
|
||||
internet connection. For IRC operation you also need
|
||||
`twisted.words <http://twistedmatrix.com/trac/wiki/TwistedWords>`_. This
|
||||
is available simply as a package *python-twisted-words* in many Linux
|
||||
distros, or directly downloadable from the link.
|
||||
|
||||
<wiki:toc max\_depth
|
||||
|
||||
"3" />
|
||||
======
|
||||
|
||||
Configuring IRC =
|
||||
|
||||
To configure IRC, you'll need to activate it in your settings file. You
|
||||
do this by copying the ``IRC_ENABLED`` flag from
|
||||
``evennia/src/config_defaults.py`` into your
|
||||
``evennia/game/settings.py`` and setting it to ``True``.
|
||||
|
||||
Start Evennia and log in as a privileged user. You should now have a new
|
||||
command availabele: ``@irc2chan``. This command is called like this:
|
||||
|
||||
::
|
||||
|
||||
@irc2chan[/switches] <evennia_channel> = <ircnetwork> <port> <#irchannel> <botname>
|
||||
|
||||
If you already know how IRC works, this should be pretty self-evident to
|
||||
use. Read the help entry for more features.
|
||||
|
||||
Setting up IRC, step by step
|
||||
----------------------------
|
||||
|
||||
You can connect IRC to any Evennia channel, but for testing, let's set
|
||||
up a new channel ``irc``.
|
||||
|
||||
::
|
||||
|
||||
@ccreate irc = This is connected to an irc channel!
|
||||
|
||||
You will automatically join the new channel.
|
||||
|
||||
Next we will create a connection to an external IRC network and channel.
|
||||
There are many, many IRC nets.
|
||||
`Here <http://www.irchelp.org/irchelp/networks/popular.html>`_ is a list
|
||||
of some of the biggest ones, the one you choose is not really very
|
||||
important unless you want to connect to a particular channel (also make
|
||||
sure that the network allows for "bots" to connect).
|
||||
|
||||
For testing, we choose the *Freenode* network, ``irc.freenode.net``. We
|
||||
will connect to a test channel, let's call it *#myevennia-test* (an IRC
|
||||
channel always begins with ``#``). It's best if you pick an obscure
|
||||
channel name that didn't exist previously - if it didn't exist it will
|
||||
be created for you. *Don't* connect to ``#evennia``, that is Evennia's
|
||||
official chat channel!
|
||||
|
||||
A *port* needed depends on the network. For Freenode this is ``6667``.
|
||||
|
||||
What will happen is that your Evennia server will connect to this IRC
|
||||
channel as a normal user. This "user" (or "bot") needs a name, which you
|
||||
must also supply. Let's call it "mud-bot".
|
||||
|
||||
To test that the bot connects correctly you also want to log onto this
|
||||
channel with a separate, third-party IRC client. There are hundreds of
|
||||
such clients available. If you use Firefox, the *Chatzilla* plugin is
|
||||
good and easy. There are also web-based clients like *Mibbit* that you
|
||||
can try. Once you have connected to a network, the command to join is
|
||||
usually ``/join channelname`` (don't forget the #).
|
||||
|
||||
Next we connect Evennia with the IRC channel.
|
||||
|
||||
::
|
||||
|
||||
@irc2chan irc = irc.freenode.net 6667 #myevennia-test mud-bot
|
||||
|
||||
Evennia will now create a new IRC bot ``mud-bot`` and connect it to the
|
||||
IRC network and the channel #myevennia. If you are connected to the IRC
|
||||
channel you will soon see the user *mud-bot* connect.
|
||||
|
||||
Write something in the Evennia channel *irc*.
|
||||
|
||||
::
|
||||
|
||||
irc Hello, World! [irc] Anna: Hello, World!
|
||||
|
||||
If you are viewing your IRC channel with a separate IRC client you
|
||||
should see your text appearing there, spoken by the bot:
|
||||
|
||||
::
|
||||
|
||||
mud-bot> [irc] Anna: Hello, World!
|
||||
|
||||
Write ``Hello!`` in your IRC client window and it will appear in your
|
||||
normal channel, marked with the name of the IRC channel you used
|
||||
(#evennia here).
|
||||
|
||||
::
|
||||
|
||||
[irc] Anna@#myevennia-test: Hello!
|
||||
|
||||
Your Evennia gamers can now chat with users on external IRC channels!
|
||||
|
||||
Talking between IRC and IMC
|
||||
---------------------------
|
||||
|
||||
You can easily connect IRC and IMC by simply connecting them to the same
|
||||
Evennia channel. IMC connections are described `here <IMC2.html>`_.
|
||||
28
docs/sphinx/source/wiki/Index.rst
Normal file
28
docs/sphinx/source/wiki/Index.rst
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
Evennia Documentation
|
||||
=====================
|
||||
|
||||
This is Evennia's manual. You should hopefully find all you need to know
|
||||
about coding with, extending and using the codebase among these pages.
|
||||
|
||||
The documentation is divided into several main categories, selectable
|
||||
below or from the left sidebar. If you are new, it might be an idea to
|
||||
browse the sections in the order they are listed. For more help, see the
|
||||
`how to get and give help <HowToGetAndGiveHelp.html>`_ page.
|
||||
|
||||
Sections
|
||||
--------
|
||||
|
||||
- A `Lengthier introduction <EvenniaIntroduction.html>`_ to what
|
||||
Evennia is.
|
||||
|
||||
- The `Getting Started <GettingStarted.html>`_ page helps with
|
||||
downloading, installing and setting up Evennia for the first time.
|
||||
- The `Administrative Documentation <AdminDocs.html>`_ covers the
|
||||
practicalities of running and maintaining an Evennia game once it is
|
||||
in place.
|
||||
- The `Builder Docs <BuilderDocs.html>`_ section contains instructions
|
||||
for starting to build a game world using Evennia.
|
||||
- The `Developer Central <DeveloperCentral.html>`_ covers
|
||||
implementation details and guides of interest for game-world coders
|
||||
as well as for current and prospective Evennia developers.
|
||||
|
||||
68
docs/sphinx/source/wiki/Internationalization.rst
Normal file
68
docs/sphinx/source/wiki/Internationalization.rst
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
Internationalization
|
||||
====================
|
||||
|
||||
*Internationalization* (often abbreviated *i18n* since there are 18
|
||||
characters between the first "i" and the last "n" in that word) allows
|
||||
Evennia's core server to return texts in other languages than English -
|
||||
without anyone having to go in and add it manually. Take a look at the
|
||||
``locale`` directory of the Evennia installation. there you will find
|
||||
which languages are currently supported.
|
||||
|
||||
Note, what is translated in this way are hard-coded strings from the
|
||||
server, things like "Connection closed" or "Server restarted".
|
||||
Basically, the things users are not supposed to change on their own.
|
||||
This means that the default command set is *not* translated. The reason
|
||||
for this is that commands are *intended* to be modified by users. .
|
||||
|
||||
Changing server language
|
||||
------------------------
|
||||
|
||||
Change language by copy&pasting the following from the default file to
|
||||
your ``game/settings.py`` file:
|
||||
|
||||
::
|
||||
|
||||
USE_I18N = True LANGUAGE_CODE = 'en'
|
||||
|
||||
Here ``'en'`` should be changed to the abbreviation for one of the
|
||||
supported languages found in ``locale/``. Restart the server to activate
|
||||
i18n.
|
||||
|
||||
Translating Evennia
|
||||
-------------------
|
||||
|
||||
If you cannot find your language in ``locale/`` it's because noone has
|
||||
translated it yet. Alternatively you might find the language but find
|
||||
the translation bad ... You are welcome to help improve the situation!
|
||||
|
||||
To start a new translation, place yourself in Evennia's root directory
|
||||
and run
|
||||
|
||||
::
|
||||
|
||||
django-admin makemessages -l <language-code>
|
||||
|
||||
where ``<language-code`` is the two-letter locale code for the language
|
||||
you want, like 'sv' for Swedish or 'es' for Spanish.
|
||||
|
||||
Next head to ``locale/<language-code>/LC_MESSAGES`` and edit the
|
||||
``*.po`` file you find there. There is no need to edit this file using a
|
||||
normal text editor -- best is to use a po-file editor from the web
|
||||
(search the web for "po editor" for many free alternatives).
|
||||
|
||||
The concept of translating is simple, it's just a matter of taking the
|
||||
english strings you find in the ``*.po`` file and add your language's
|
||||
translation best you can. When you are done, send the ``*.po`` file to
|
||||
the Evennia developer list so we can integrate your translation it into
|
||||
Evennia!
|
||||
|
||||
Finally, you need to compile your translation into a more efficient
|
||||
form.
|
||||
|
||||
::
|
||||
|
||||
django-admin.py compilemessages
|
||||
|
||||
This will go through all languages and create/update compiled files
|
||||
(``*.mo``) for them. This needs to be done whenever a ``*.po`` file is
|
||||
updated.
|
||||
50
docs/sphinx/source/wiki/Licensing.rst
Normal file
50
docs/sphinx/source/wiki/Licensing.rst
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
Evennia Licence
|
||||
===============
|
||||
|
||||
Evennia is licensed under the very friendly *Modified Clarified Artistic
|
||||
License*. You can find the license as ``LICENCE`` in the Evennia root
|
||||
directory. You can also read the full license file
|
||||
`here <http://code.google.com/p/evennia/source/browse/trunk/LICENSE>`_.
|
||||
|
||||
Licence FAQ
|
||||
-----------
|
||||
|
||||
You should read the full license file to know what it says exactly, but
|
||||
here are some answers to common questions.
|
||||
|
||||
Q: I have created a game using Evennia, what does the license allow me
|
||||
to do with it?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
**A:** It's your own world to do with what you please! In summary, a
|
||||
MU``*`` world you create using Evennia (i.e. the files you create in
|
||||
``game``) falls under **§6** of the license (it's a sort of "library").
|
||||
So your game world and all its contents belongs to you (as it should
|
||||
be). Keep it to yourself or re-distribute it under any license of your
|
||||
choice - or sell it and become filthy rich for all we care.
|
||||
|
||||
Q: I have modified Evennia itself, what does the license say about that?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
**A:** The Evennia package itself (i.e. the stuff you download from us)
|
||||
is referred to as "The Package", "Standard version" in the license.
|
||||
|
||||
- If you just fixed a typo or bug, that falls under **§2** - that is,
|
||||
you don't *have* to do anything to appease the license. Regardless,
|
||||
we'd of course appreciate it if you submitted bugs/fixes to us so
|
||||
Evennia becomes more complete!.
|
||||
- If you made other modifications or added new features to the server,
|
||||
that's also ok, but falls under **§3** - you must make a clear note
|
||||
of the changes as well as put the changes into the public domain or
|
||||
make separate arrangements with us (since it's then no longer a
|
||||
"Standard version"). Of course, if you plan to add new features to
|
||||
the server, the easiest way to do so is to simply become an Evennia
|
||||
developer!
|
||||
|
||||
Q: Can I re-distribute Evennia along with my custom game implementation?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
**A:** Sure. This is covered in **§4** - just package the "Standard
|
||||
version" (that is, the one you download from us) with your package. Make
|
||||
sure to include the original license and disclaimers and note where
|
||||
users may get it if they want to download it of their own.
|
||||
60
docs/sphinx/source/wiki/Links.rst
Normal file
60
docs/sphinx/source/wiki/Links.rst
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
External links and resources
|
||||
============================
|
||||
|
||||
This is a list of resources that may be useful for Evennia users and
|
||||
developers.
|
||||
|
||||
Evennia links
|
||||
-------------
|
||||
|
||||
- `Evennia's main portal page <http://www.evennia.com>`_ (RSS feeds to
|
||||
updates)
|
||||
- `Evennia forums <http://www.evennia.com/discussions>`_
|
||||
- `Evennia Commit
|
||||
Log <http://groups.google.com/group/evennia-commits>`_ (SVN commit
|
||||
notification)
|
||||
- `Sequential source update
|
||||
list <http://code.google.com/p/evennia/source/list>`_ (easily see
|
||||
what was changed in each update)
|
||||
- `Evennia mailing list <http://groups.google.com/group/evennia>`_
|
||||
(better web interface can be found from the portal)
|
||||
|
||||
Third-party Evennia links
|
||||
-------------------------
|
||||
|
||||
- `Hosting Evennia on
|
||||
Webfaction <http://lotek.heavy.ch/evennia#Hosting>`_
|
||||
- `Evennia on Ohloh <http://www.ohloh.net/projects/6906>`_
|
||||
- `Evennia on OpenHatch <http://openhatch.org/+projects/Evennia>`_
|
||||
- `Evennia on
|
||||
PyPi <http://pypi.python.org/pypi/Evennia%20MUD%20Server/Alpha>`_
|
||||
|
||||
Frameworks
|
||||
----------
|
||||
|
||||
`Django's homepage <http://www.djangoproject.com/>`_
|
||||
|
||||
- `Documentation <http://docs.djangoproject.com/en>`_
|
||||
- `Code <http://code.djangoproject.com/>`_
|
||||
|
||||
`Twisted homepage <http://twistedmatrix.com/>`_
|
||||
|
||||
- `Documentation <http://twistedmatrix.com/documents/current/core/howto/index.html>`_
|
||||
- `Code <http://twistedmatrix.com/trac/browser>`_
|
||||
|
||||
Tools
|
||||
-----
|
||||
|
||||
- `Subversion Manual <http://svnbook.red-bean.com/>`_
|
||||
- `Doxygen <http://www.stack.nl/~dimitri/doxygen/>`_ (build auto-docs)
|
||||
|
||||
Python Info
|
||||
-----------
|
||||
|
||||
`Python Website <http://www.python.org/>`_
|
||||
|
||||
- `Documentation <http://www.python.org/doc/>`_
|
||||
- `Tutorial <http://docs.python.org/tut/tut.html>`_
|
||||
- `Library Reference <http://docs.python.org/lib/lib.html>`_
|
||||
- `Language Reference <http://docs.python.org/ref/ref.html>`_
|
||||
|
||||
411
docs/sphinx/source/wiki/Locks.rst
Normal file
411
docs/sphinx/source/wiki/Locks.rst
Normal file
|
|
@ -0,0 +1,411 @@
|
|||
<wiki:toc max\_depth
|
||||
|
||||
"3" />
|
||||
======
|
||||
|
||||
Locks =
|
||||
|
||||
For most games it is a good idea to restrict what people can do. In
|
||||
Evennia such restrictions are applied and checked by something called
|
||||
*locks*. All Evennia entities (`commands <Commands.html>`_,
|
||||
`objects <Objects.html>`_, `scripts <Scripts.html>`_,
|
||||
`players <Players.html>`_, `help system <HelpSystem.html>`_,
|
||||
`messages <Communications#Msg.html>`_ and
|
||||
`channels <Communications#Channels.html>`_) are accessed through locks.
|
||||
|
||||
A lock can be thought of as an "access rule" restricting a particular
|
||||
use of an Evennia entity. Whenever another entity wants that kind of
|
||||
access the lock will analyze that entity in different ways to determine
|
||||
if access should be granted or not. Evennia implements a "lockdown"
|
||||
philosophy - all entities are inaccessible unless you explicitly define
|
||||
a lock that allows some or full access.
|
||||
|
||||
Let's take an example: An object has a lock on itself that restricts how
|
||||
people may "delete" that object. Apart from knowing that it restricts
|
||||
deletion, the lock also knows that only players with the specific ID of,
|
||||
say, '34' are allowed to delete it. So whenever a player tries to run
|
||||
@delete on the object, the @delete command makes sure to check if this
|
||||
player is really allowed to do so. It calls the lock, which in turn
|
||||
checks if the player's id is 34. Only then will it allow @delete to go
|
||||
on with its job.
|
||||
|
||||
Setting and checking a lock
|
||||
---------------------------
|
||||
|
||||
The in-game command for setting locks on objects is ``@lock``:
|
||||
|
||||
::
|
||||
|
||||
> @lock obj = <lockstring>
|
||||
|
||||
The ``<lockstring>`` is a string on a certain form that defines the
|
||||
behaviour of the lock. We will go into more detail on how
|
||||
``<lockstring>`` should look in the next section.
|
||||
|
||||
Code-wise, Evennia handles locks through what is usually called
|
||||
``locks`` on all relevant entities. This is a handler that allows you to
|
||||
add, delete and check locks.
|
||||
|
||||
::
|
||||
|
||||
myobj.locks.add(<lockstring>)
|
||||
|
||||
One can call ``locks.check()`` to perform a lock check, but to hide the
|
||||
underlying implementation all objects also have a convenience function
|
||||
called ``access``. This should preferably be used. In the example below,
|
||||
``accessing_obj`` is the object requesting the 'delete' access. This is
|
||||
how it would (and do) look from inside the ``@delete`` command:
|
||||
|
||||
::
|
||||
|
||||
if not obj.access(accessing_obj, 'delete'): accessing_obj.msg("Sorry, you may not delete that.") return
|
||||
|
||||
Defining locks
|
||||
--------------
|
||||
|
||||
Defining a lock (i.e. an access restriction) in Evennia is done by
|
||||
adding simple strings of lock definitions to the object's ``locks``
|
||||
property using ``obj.locks.add()``. Such a *lockstring* formally looks
|
||||
like this:
|
||||
|
||||
::
|
||||
|
||||
access_type:[NOT] func1([arg1,..])[[AND|OR][ NOT] func2([arg1,...])[...]]
|
||||
|
||||
where ``[..]`` marks optional parts. AND, OR and NOT are not case
|
||||
sensitive and excess spaces are ignored. ``func1, func2`` etc are
|
||||
special *lock functions* available to the lock system.
|
||||
|
||||
This form of writing may look complicated, so let's immediately give
|
||||
some much nicer examples:
|
||||
|
||||
::
|
||||
|
||||
delete:id(34) # only allow obj #34 to delete edit:all() # let everyone edit get: not attr(very_weak) or perm(Wizard) # only those who are not "very_weak" or are Wizards may pick this up
|
||||
|
||||
So, a lockstring consists of the type of restriction (the
|
||||
``access_type``), a colon (``:``) and then a list of function calls that
|
||||
determine what is needed to pass the lock. Each function returns either
|
||||
``True`` or ``False``. AND/OR and NOT works like normal Python to
|
||||
combine several function checks. If the total result is True, the lock
|
||||
is passed.
|
||||
|
||||
You can create several lock types one after the other by separating them
|
||||
with a semicolon (``;``) in the lockstring. The string below is
|
||||
identical to the first two rows of the previous example:
|
||||
|
||||
::
|
||||
|
||||
delete:id(34);edit:all()
|
||||
|
||||
Valid access\_types
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
An ``access_type``, the first part of a lockstring, defines what kind of
|
||||
capability a lock controls, such as "delete" or "edit". You may in
|
||||
principle name your ``access_type`` anything as long as it is unique for
|
||||
the particular object. Access\_types are not case-sensitive.
|
||||
|
||||
If you want to make sure the lock is used however, you should pick
|
||||
``access_type`` names that you (or the default command set) actually
|
||||
tries, as in the example of ``@delete`` above that uses the 'delete'
|
||||
``access_type``.
|
||||
|
||||
Below are the access\_types checked by the default commandset.
|
||||
|
||||
`Commands <Commands.html>`_: ``cmd`` - this defines who may call this
|
||||
command at all.
|
||||
|
||||
`Objects <Objects.html>`_:
|
||||
|
||||
- ``control`` - who is the "owner" of the object. Can set locks, delete
|
||||
it etc. Defaults to the creator of the object.
|
||||
- ``call`` - who may call object-commands on this object.
|
||||
- ``examine`` - who may examine this object's properties.
|
||||
- ``delete`` - who may delete the object.
|
||||
- ``edit`` - who may edit properties and attributes of the object.
|
||||
- ``get``- who may pick up the object and carry it around.
|
||||
- ``puppet`` - who may "become" this object and control it as their
|
||||
"character".
|
||||
|
||||
`Characters <Objects#Characters.html>`_: ``<Same as Objects>``
|
||||
|
||||
`Exits <Objects#Exits.html>`_: ``<Same as Objects>`` + ``traverse`` -
|
||||
who may pass the exit.
|
||||
|
||||
`Players <Players.html>`_:
|
||||
|
||||
- ``examine`` - who may examine the player's properties.
|
||||
- ``delete`` - who may delete the player.
|
||||
- ``edit`` - who may edit the player's attributes and properties.
|
||||
- ``msg`` - who may send messages to the player.
|
||||
- ``boot`` - who may boot the player.
|
||||
|
||||
`Attributes <Attributes.html>`_: ``<None>``
|
||||
|
||||
`Channels <Communications#Channels.html>`_:
|
||||
|
||||
- ``control`` - who is administrating the channel. This means the
|
||||
ability to delete the channel, boot listeners etc.
|
||||
- ``send`` - who may send to the channel.
|
||||
- ``listen`` - who may subscribe and listen to the channel.
|
||||
|
||||
`HelpEntry <HelpSystem.html>`_:
|
||||
|
||||
- ``examine`` - who may view this help entry (usually everyone)
|
||||
- ``edit`` - who may edit this help entry.
|
||||
|
||||
So to take an example, whenever an exit is to be traversed, a lock of
|
||||
the type *traverse* will be checked. Defining a suitable lock type for
|
||||
an exit object would thus involve a lockstring
|
||||
``traverse: <lock functions>``.
|
||||
|
||||
Lock functions
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
You are not allowed to use just any function in your lock definition;
|
||||
you are infact only allowed to use those functions defined in one of the
|
||||
modules given in ``settings.LOCK_FUNC_MODULES``. All functions in any of
|
||||
those modules will automatically be considered a valid lock function.
|
||||
The default ones are found in src/locks/lockfuncs.py.
|
||||
|
||||
A lock function must always accept at least two arguments - the
|
||||
*accessing object* (this is the object wanting to get access) and the
|
||||
*accessed object* (this is the object with the lock). Those two are fed
|
||||
automatically as the first two arguments the function when the lock is
|
||||
checked. Any arguments explicitly given in the lock definition will
|
||||
appear as extra arguments.
|
||||
|
||||
::
|
||||
|
||||
# A simple example lock function. Called with e.g. id(34)def id(accessing_obj, accessed_obj, *args, **kwargs): if args: wanted_id = args[0] return accessing_obj.id == wanted_id return False
|
||||
|
||||
(Using the ``*`` and ``**`` syntax causes Python to magically put all
|
||||
extra arguments into a list ``args``and all keyword arguments into a
|
||||
dictionary ``kwargs`` respectively. If you are unfamiliar with how
|
||||
``*args`` and ``**kwargs`` work, see the Python manuals).
|
||||
|
||||
Some useful default lockfuncs (see lockfuncs.py for a full list):
|
||||
|
||||
- ``true()/all()`` - give access to everyone
|
||||
- ``false()/none()/superuser()`` - give access to noone. Superusers
|
||||
bypass the check entirely.
|
||||
- ``perm(perm)`` - this tries to match a given ``permission`` property.
|
||||
See `below <Locks#Permissions.html>`_.
|
||||
- ``perm_above(perm)`` - requres a "higher" permission level than the
|
||||
one given.
|
||||
- ``id(num)/dbref(num)`` - checks so the accessobject has a certain
|
||||
dbref/id.
|
||||
- ``attr(attrname)`` - checks if a certain
|
||||
`Attribute <Attributes.html>`_ exists on accessingobject.
|
||||
- ``attr(attrname, value)`` - checks so an attribute exists on
|
||||
accessing*object*and has the given value.
|
||||
- ``attr_gt(attrname, value)`` - checks so accessingobject has a value
|
||||
larger (>) than the given value.
|
||||
- ``attr_ge, attr_lt, attr_le, attr_ne`` - corresponding for >
|
||||
|
||||
, <, <
|
||||
======
|
||||
|
||||
and !=.
|
||||
|
||||
- ``holds(objid)`` - checks so the accessing objects contains an object
|
||||
of given name or dbref.
|
||||
- ``pperm(perm)``, ``pid(num)/pdbref(num)`` - same as ``perm``,
|
||||
``id/dbref`` but always looks for permissions and dbrefs of
|
||||
*Players*, not on Characters.
|
||||
|
||||
Default locks
|
||||
-------------
|
||||
|
||||
Evennia sets up a few basic locks on all new objects and players (if we
|
||||
didn't, noone would have any access to anything from the start). This is
|
||||
all defined in the root `Typeclasses <Typeclass.html>`_ of the
|
||||
respective entity, in the hook method ``basetype_setup()`` (which you
|
||||
usually don't want to edit unless you want to change how basic stuff
|
||||
like rooms and exits store their internal variables). This is called
|
||||
once, before ``at_object_creation``, so just put them in the latter
|
||||
method on your child object to change the default. Also creation
|
||||
commands like ``@create`` changes the locks of objects you create - for
|
||||
example it sets the ``control`` lock\_type allow youm, its creator to
|
||||
control and delete the object.
|
||||
|
||||
Permissions
|
||||
===========
|
||||
|
||||
A *permission* is simply a list of text strings stored on the property
|
||||
``permissions`` on ``Objects`` and ``Players``. Permissions can be used
|
||||
as a convenient way to structure access levels and hierarchies. It is
|
||||
set by the ``@perm`` command.
|
||||
|
||||
::
|
||||
|
||||
@perm Tommy = Builders
|
||||
|
||||
All new players/character are given a default set of permissions defined
|
||||
by ``settings.PERMISSION_PLAYER_DEFAULT``.
|
||||
|
||||
Selected permission strings can be organized in a *permission hierarchy*
|
||||
by editing the tuple ``settings.PERMISSION_HIERARCHY``. Evennia's
|
||||
default permission hierarchy is as follows:
|
||||
|
||||
::
|
||||
|
||||
Immortals Wizards Builders PlayerHelpers Players # this is what all new Players start with by default
|
||||
|
||||
The main use of this is that if you use the lock function ``perm()``
|
||||
mentioned above, a lock check for a particular permission in the
|
||||
hierarchy will *also* grant access to those with *higher* hierarchy
|
||||
acces. So if you have the permission "Wizards" you will also pass a lock
|
||||
defined as ``perm(Builders)`` or any of those levels below "Wizards".
|
||||
The lock function ``perm_above(Players)`` require you to have a
|
||||
permission level higher than ``Players`` and so on. If the permission
|
||||
looked for is not in the hierarchy, an exact match is required.
|
||||
|
||||
::
|
||||
|
||||
obj1.permissions = ["Builders", "cool_guy"] obj2.locks.add("enter:perm_above(Players) and perm(cool_guy)")obj2.access(obj1, "enter") # this returns True!
|
||||
|
||||
Superusers
|
||||
----------
|
||||
|
||||
There is normally only one *superuser* account and that is the the one
|
||||
first created when starting Evennia (User #1). This is sometimes known
|
||||
as the "Owner" or "God" user. A superuser has more than full access - it
|
||||
completely *bypasses* all locks so no checks are even run. This allows
|
||||
for the superuser to always have access to everything in an emergency.
|
||||
But it also hides any eventual errors you might have made in your lock
|
||||
definitions. So when trying out game systems you should use a secondary
|
||||
character rather than #1 so your locks get tested correctly.
|
||||
|
||||
More Lock definition examples
|
||||
=============================
|
||||
|
||||
::
|
||||
|
||||
examine: attr(eyesight, excellent) or perm(Builders)
|
||||
|
||||
You are only allowed to do *examine* on this object if you have
|
||||
'excellent' eyesight or is a Builder.
|
||||
|
||||
::
|
||||
|
||||
# lock for the tell command
|
||||
cmd: perm(Builders) and not perm(no_tell)
|
||||
|
||||
Locks can be used to implement highly specific bans. Set this on e.g.
|
||||
the ``tell`` command, then give a player the "permission" ``no_tell`` to
|
||||
disable their use of this particular command henceforth.
|
||||
|
||||
::
|
||||
|
||||
open: holds('the green key') or perm(Builder)
|
||||
|
||||
This could be called by the ``open`` command on a "door" object. The
|
||||
check is passed if you are a Builder or has the right key in your
|
||||
inventory.
|
||||
|
||||
::
|
||||
|
||||
# this limits what commands are visible to the user
|
||||
cmd: perm(Builders)
|
||||
|
||||
Evennia's command handler looks for a lock of type ``cmd`` to determine
|
||||
if a user is allowed to even call upon a particular command or not. When
|
||||
you define a command, this is the kind of lock you must set. See the
|
||||
default command set for lots of examples.
|
||||
|
||||
::
|
||||
|
||||
dbref = caller.id
|
||||
lockstring = "control:id(%s);examine:perm(Builders);delete:id(%s) or perm(Wizards);get:all()" % (dbref, dbref)
|
||||
new_obj.locks.add(lockstring)
|
||||
|
||||
This is how the ``@create`` command sets up new objects. In sequence,
|
||||
this permission string sets the owner of this object be the creator (the
|
||||
one running ``@create``). Builders may examine the object whereas only
|
||||
Wizards and the creator may delete it. Everyone can pick it up.
|
||||
|
||||
A complete example of setting locks on an object
|
||||
================================================
|
||||
|
||||
Assume we have two objects - one is ourselves (not superuser) and the
|
||||
other is an `Object <Objects.html>`_ called ``box``.
|
||||
|
||||
::
|
||||
|
||||
> @create/drop box > @desc box = "This is a very big and heavy box."
|
||||
|
||||
We want to limit which objects can pick up this heavy box. Let's say
|
||||
that to do that we require the would-be lifter to to have an attribute
|
||||
*strength* on themselves, with a value greater than 50. We assign it to
|
||||
ourselves to begin with.
|
||||
|
||||
::
|
||||
|
||||
> @set self/strength = 45
|
||||
|
||||
Ok, so for testing we made ourselves strong, but not strong enough. Now
|
||||
we need to look at what happens when someone tries to pick up the the
|
||||
box - they use the ``get`` command (in the default set). This is defined
|
||||
in ``game/gamesrc/commands/default/general.py``. In its code we find
|
||||
this snippet:
|
||||
|
||||
::
|
||||
|
||||
if not obj.access(caller, 'get'): if obj.db.get_err_msg: caller.msg(obj.db.get_err_msg) else: caller.msg("You can't get that.") return
|
||||
|
||||
So the ``get`` command looks for a lock with the type *get* (not so
|
||||
surprising). It also looks for an `Attribute <Attributes.html>`_ on the
|
||||
checked object called *get*err*msg* in order to return a customized
|
||||
error message. Sounds good! Let's start by setting that on the box:
|
||||
|
||||
::
|
||||
|
||||
> @set box/get_err_msg = You are not strong enough to lift this box.
|
||||
|
||||
Next we need to craft a Lock of type *get* on our box. We want it to
|
||||
only be passed if the accessing object has the attribute *strength* of
|
||||
the right value. For this we would need to create a lock function that
|
||||
checks if attributes have a value greater than a given value. Luckily
|
||||
there is already such a one included in evennia (see
|
||||
``src/permissions/lockfuncs.py``), called``attr_gt``.
|
||||
|
||||
So the lock string will look like this: "``get:attr_gt(strength, 50)``".
|
||||
We put this on the box now:
|
||||
|
||||
::
|
||||
|
||||
@lock box = get:attr_gt(strength, 50)
|
||||
|
||||
Try to ``get`` the object and you should get the message that we are not
|
||||
strong enough. Increase your strength above 50 however and you'll pick
|
||||
it up no problem. Done! A very heavy box!
|
||||
|
||||
If you wanted to set this up in python code, it would look something
|
||||
like this:
|
||||
|
||||
::
|
||||
|
||||
from src.utils import create box = create.create_object(None, key="box", locks="get:attr_gt(strength, 50)")# or, if we don't set the locks right awaybox.locks.add("get:attr_gt(strength, 50)")# set the attributesbox.db.desc = "This is a very big and heavy box." box.db.get_err_msg = "You are not strong enough to lift this box."# one heavy box, ready to withstand all but the strongest...
|
||||
|
||||
On Django's permission system
|
||||
=============================
|
||||
|
||||
Django also implements a comprehensive permission/security system out of
|
||||
the box. The reason we don't use that is because it is app-centric (app
|
||||
in the Django sense). Its permission strings are of the form
|
||||
``appname.permstring`` and it automatically adds three of them for each
|
||||
database model in the app - for the app src/object this would be for
|
||||
example 'object.create', 'object.admin' and 'object.edit'. This makes a
|
||||
lot of sense for a web application, not so much for a MUD, especially
|
||||
when we try to hide away as much of the underlying architecture as
|
||||
possible.
|
||||
|
||||
The django permissions are not completely gone however. We use it for
|
||||
logging in users (the ``User`` object tied to `Players <Players.html>`_
|
||||
is a part of Djangos's auth system). It is also used exclusively for
|
||||
managing Evennia's web-based admin site, which is a graphical front-end
|
||||
for the database of Evennia. You edit and assign such permissions
|
||||
directly from the web interface. It's stand-alone from the permissions
|
||||
described above.
|
||||
94
docs/sphinx/source/wiki/Nicks.rst
Normal file
94
docs/sphinx/source/wiki/Nicks.rst
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
Nicks
|
||||
=====
|
||||
|
||||
*Nicks*, short for *Nicknames* is a system allowing an object (usually a
|
||||
`Player Character <Players.html>`_) to assign custom replacement names
|
||||
for other game entities.
|
||||
|
||||
Nicks are not to be confused with *Aliases*. Setting an Alias on a game
|
||||
entity actually changes an inherent attribute on that entity, and
|
||||
everyone in the game will be able to use that alias to address the
|
||||
entity thereafter. A *Nick* on the other hand, is an alternate name *you
|
||||
alone* can use to refer to that entity. The nicknamed entitity is not
|
||||
changed in any way. The principle is very simple - Evennia simply scans
|
||||
your input looking for a defined nick and replaces it with the full,
|
||||
"real" name before passing it on. In the default system nicks are
|
||||
controlled with the simple ``nick`` command, but the system can be
|
||||
expanded for other uses too.
|
||||
|
||||
Default Evennia use Nicks in three flavours that determine when Evennia
|
||||
actually tries to do the substitution.
|
||||
|
||||
- inputline - replacement is attempted whenever you write anything on
|
||||
the command line. This is the default.
|
||||
- objects - replacement is only attempted when referring an object
|
||||
- players - replacement is only attempted when referring a player
|
||||
|
||||
Here's how to use it in the default command set (using the ``nick``
|
||||
command):
|
||||
|
||||
::
|
||||
|
||||
nick ls = look
|
||||
|
||||
This is a good one for unix/linux users who are accustomed to using the
|
||||
``ls`` command in their daily life. It is equivalent to
|
||||
``nick/inputline ls = look``.
|
||||
|
||||
::
|
||||
|
||||
nick/object mycar2 = The red sports car
|
||||
|
||||
With this example, substitutions will only be done specifically for
|
||||
commands expecting an object reference, such as
|
||||
|
||||
::
|
||||
|
||||
look mycar2
|
||||
|
||||
becomes equivalent to "``look The red sports car``".
|
||||
|
||||
::
|
||||
|
||||
nick/players tom = TommyBoy
|
||||
|
||||
This is useful for commands searching for players explicitly:
|
||||
|
||||
::
|
||||
|
||||
@find *tom
|
||||
|
||||
One can use nicks to speed up input. Below we add ourselves a quicker
|
||||
way to build red buttons. In the future just writing *rb* will be enough
|
||||
to execute that whole long string.
|
||||
|
||||
::
|
||||
|
||||
nick rb = @create button:examples.red_button.RedButton
|
||||
|
||||
Nicks could also be used as the start for building a "recog" system
|
||||
suitable for an RP mud.
|
||||
|
||||
::
|
||||
|
||||
nick/player Arnold = The mysterious hooded man
|
||||
|
||||
Coding with nicks
|
||||
-----------------
|
||||
|
||||
Nicks are are stored as the ``Nick`` database model and are referred
|
||||
from the normal Evennia `object <Objects.html>`_ through the ``nicks``
|
||||
property. ``nicks`` is a special handler that offers effective error
|
||||
checking, searches and conversion.
|
||||
|
||||
::
|
||||
|
||||
# A command/channel nick: object.nicks.add("greetjack", "tell Jack = Hello pal!")# An object nick: object.nicks.add("rose", "The red flower", nick_type="object")# An player nick: object.nicks("tom", "Tommy Hill", nick_type="player")# My own custom nick type (handled by my own game code somehow): object.nicks.add("hood", "The hooded man", nick_type="my_identsystem")# get back the translated nick: full_name = object.nicks.get("rose", nick_type="object")# delete a previous set nick object.nicks.del("rose", nick_type="object")
|
||||
|
||||
In a command definition you can reach the nick handler through
|
||||
``self.caller.nicks``. See the ``nick`` command in
|
||||
``game/gamesrc/commands/default/general.py`` for more examples.
|
||||
|
||||
As a last note, The Evennia `channel <Communications.html>`_ alias
|
||||
systems are using nicks with the ``nick_type="channel"`` in order to
|
||||
allow users to create their own custom aliases to channels.
|
||||
192
docs/sphinx/source/wiki/Objects.rst
Normal file
192
docs/sphinx/source/wiki/Objects.rst
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
Objects
|
||||
=======
|
||||
|
||||
All in-game objects in Evennia, be it characters, chairs, monsters,
|
||||
rooms or hand grenades are represented by an Evennia *Object*. Objects
|
||||
form the core of Evennia and is probably what you'll spend most time
|
||||
working with. Objects are `TypeClassed <Typeclasses.html>`_ entities.
|
||||
|
||||
How to create your own object types
|
||||
-----------------------------------
|
||||
|
||||
An Evennia Object is, per definition, a Python class that includes
|
||||
``src.objects.objects.Object`` among its parents (if you are aware of
|
||||
how typeclasses work, this is a typeclass linked to the ``ObjectDB``
|
||||
database model). In your code you can however conveniently refer to
|
||||
``game.gamesrc.objects.baseobjects.Object`` instead.
|
||||
|
||||
Here's how to define a new Object typeclass in code:
|
||||
|
||||
::
|
||||
|
||||
from game.gamesrc.objects.baseobjects import Objectclass Rose(Object): """ This creates a simple rose object """ at_object_creation(self): "this is called only once, when object is first created" # add a persistent attribute 'desc' to object. self.db.desc = "This is a pretty rose with thorns."
|
||||
|
||||
Save your class to a module under ``game/gamesrc/objects``, say
|
||||
``flowers.py``. Now you just need to point to the class *Rose* with the
|
||||
``@create`` command to make a new rose:
|
||||
|
||||
::
|
||||
|
||||
> @create/drop MyRose:flowers.Rose
|
||||
|
||||
To create a new object in code, use the method
|
||||
``src.utils.create.create_object()``:
|
||||
|
||||
::
|
||||
|
||||
from src.utils import create new_rose = create.create_object("game.gamesrc.objects.flowers.Rose", key="MyRose")
|
||||
|
||||
(You have to give the full path to the class in this case.
|
||||
``create.create_object`` is a powerful function that should be used for
|
||||
all coded creating. Check out the module for more info on which
|
||||
arguments you can give the function.)
|
||||
|
||||
This particular class doesn't really do much, all it does it make sure
|
||||
the attribute ``desc``(which is what the ``look`` command looks for) is
|
||||
pre-set. You could just as well do the same with the ``@describe``
|
||||
command. The ``Object`` typeclass offers many more hooks that is
|
||||
available to use though. Look at the ``Object`` class in
|
||||
``game/gamesrc/objects/baseobjects.py`` to orient yourself. If you
|
||||
define a new Object class (inheriting from the base one), and wants that
|
||||
to be the default instead, set ``BASE_OBJECT_TYPECLASS`` in
|
||||
``settings.py`` to point to your new class.
|
||||
|
||||
Properties and functions on Objects
|
||||
-----------------------------------
|
||||
|
||||
Beyond those properties assigned to all
|
||||
`typeclassed <Typeclasses.html>`_ objects, the Object also has the
|
||||
following custom properties:
|
||||
|
||||
- ``aliases`` - a list of alternative names for the object. Aliases are
|
||||
stored database objects, but the ``aliases`` property receives and
|
||||
returns lists - so assign to it like normal, e.g.
|
||||
``obj.aliases=['flower', 'red blossom']``
|
||||
- ``location`` - a reference to the object currently storing this
|
||||
object.
|
||||
- ``home`` is a backup location. The main motivation is to have a safe
|
||||
place to move the object to if its ``location`` is destroyed. All
|
||||
objects should usually have a home location for this reason.
|
||||
- ``destination`` - this holds a reference to another object this
|
||||
object links to in some way. Its main use is for
|
||||
`Exits <Objects#Exits.html>`_, it's otherwise usually unset.
|
||||
- ``nicks`` - as opposed to aliases, a `Nick <Nicks.html>`_ holds a
|
||||
convenient nickname replacement for a real name, word or sequence,
|
||||
only valid for this object. Nicks are stored in the database and are
|
||||
a bit more complex than aliases since they have a *type* that defines
|
||||
where Evennia tries to do the substituion. Use nicks.get(alias, type)
|
||||
to get a nick, or nicks.add(alias, realname) to add a new one.
|
||||
- ``player`` - this holds a reference to a connected
|
||||
`Player <Players.html>`_ controlling this object (if any). Note that
|
||||
this is set also if the controlling player is *not* currently online
|
||||
- to test if a server is online, use ``has_player`` instead.
|
||||
- ``sessions`` - if ``player`` field is set *and the player is online*,
|
||||
this is a list of all active sessions (server connections) to contact
|
||||
them through.
|
||||
- ``permissions`` - a list of `permission strings <Locks.html>`_ for
|
||||
defining access rights.
|
||||
- ``has_player`` - a shorthand for checking if an online player is
|
||||
currently connected to this object.
|
||||
- ``contents`` - this is a list referencing all objects 'inside' this
|
||||
object, that is which has this object set as their ``location``.
|
||||
- ``exits`` - this returns all objects inside this object that are
|
||||
*Exits*, that is, has the ``destination`` property set.
|
||||
|
||||
The last two properties are special:
|
||||
|
||||
- ``cmdset`` - this is a handler that stores all `command
|
||||
sets <Commands#Command_Sets.html>`_ defined on the object (if any).
|
||||
- ``scripts`` - this is a handler that manages
|
||||
`scripts <Scripts.html>`_ attached to the object (if any).
|
||||
|
||||
The Object also has a host of useful utility functions. See the function
|
||||
headers in ``src/objects/models.py`` for arguments and more details.
|
||||
|
||||
- ``msg`` - this function is used to send messages from the server to a
|
||||
player connected to this object.
|
||||
- ``msg_contents`` - calls ``msg`` on all objects inside this object.
|
||||
- ``search`` - this is a convenient way to search for a specific
|
||||
object, at a given location or globally.
|
||||
- ``execute_cmd`` - Lets the object execute the given string as if it
|
||||
was given on the command line.
|
||||
- ``move_to`` - perform a full move of this object to a new location.
|
||||
This is the main move method and will call all relevant hooks, do all
|
||||
checks etc.
|
||||
- ``clear_exits`` - will delete all `Exits <Objects#Exits.html>`_ to
|
||||
*and* from this object.
|
||||
- ``clear_contents`` - this will not delete anything, but rather move
|
||||
all contents (except Exits) to their designated ``Home`` locations.
|
||||
- ``delete`` - deletes this object, first calling ``clear_exits()`` and
|
||||
``clear_contents()``.
|
||||
|
||||
Objects also define a host of *hook methods* beyond
|
||||
``at_object_creation``. When implementing your custom objects, you will
|
||||
inherit from the base parent and overload these hooks with your own
|
||||
custom code. See ``game.gamesrc.baseobjects`` for an updated list of all
|
||||
the available hooks.
|
||||
|
||||
Subclasses of *Object*
|
||||
----------------------
|
||||
|
||||
There are three special subclasses of *Object* in default Evennia -
|
||||
*Characters*, *Rooms* and *Exits*. The reason they are separated is
|
||||
because these particular object types are fundamental, something you
|
||||
will always need and in some cases requires some extra attention in
|
||||
order to be recognized by the game engine. In practice they are all
|
||||
pretty similar to the base Object. You will import them all from
|
||||
``game.gamesrc.objects.baseobjects``.
|
||||
|
||||
Characters
|
||||
~~~~~~~~~~
|
||||
|
||||
Characters are objects controlled by `Players <Players.html>`_. When a
|
||||
new Player logs in to Evennia for the first time, a new ``Character``
|
||||
object is created and the Player object is assigned to the ``player``
|
||||
attribute. A ``Character`` object must have a `Default
|
||||
Commandset <Commands#Command_Sets.html>`_ set on itself at creation, or
|
||||
the player will not be able to issue any commands! If you just inherit
|
||||
your own class from ``baseobjects.Character`` and make sure the parent
|
||||
methods are run you should not have to worry about this. You can change
|
||||
the default typeclass assigned to new Players in your settings with
|
||||
``BASE_CHARACTER_TYPECLASS``.
|
||||
|
||||
Rooms
|
||||
~~~~~
|
||||
|
||||
*Rooms* are the root containers of all other objects. The only thing
|
||||
really separating a room from any other object is that they have no
|
||||
``location`` of their own and that default commands like ``@dig``
|
||||
creates objects of this class - so if you want to expand your rooms with
|
||||
more functionality, just inherit from ``baseobjects.Room``. Change the
|
||||
default used by ``@dig`` with ``BASE_ROOM_TYPECLASS``.
|
||||
|
||||
Exits
|
||||
~~~~~
|
||||
|
||||
*Exits* are objects connecting other objects (usually *Rooms*) together.
|
||||
An object named *North* or *in* might be an exit, as well as *door*,
|
||||
*portal* or *jump out the window*. An exit has two things that separate
|
||||
them from other objects. Firstly, their *destination* property is set
|
||||
and points to a valid object. This fact makes it easy and fast to locate
|
||||
exits in the database. Secondly, exits define a special `Transit
|
||||
Command <Commands.html>`_ on themselves when they are created. This
|
||||
command is named the same as the exit object and will, when called,
|
||||
handle the practicalities of moving the character to the Exits's
|
||||
*destination* - this allows you to just enter the name of the exit on
|
||||
its own to move around, just as you would expect.
|
||||
|
||||
The exit functionality is all defined on the Exit typeclass, so you
|
||||
could in principle completely change how exits work in your game (it's
|
||||
not recommended though, unless you really know what you are doing).
|
||||
Exits are `locked <Locks.html>`_ using an access*type called*traverse\_
|
||||
and also make use of a few hook methods for giving feedback if the
|
||||
traversal fails. See ``baseobjects.Exit`` for more info, that is also
|
||||
what you should inherit from to make custom exit types. Change the
|
||||
default class used by e.g. ``@dig`` and ``@open`` by editing
|
||||
``BASE_EXIT_TYPECLASS`` in your settings.
|
||||
|
||||
Further notes
|
||||
-------------
|
||||
|
||||
For a more advanced example of a customized object class, see
|
||||
``game/gamesrc/objects/examples/red_button.py``.
|
||||
121
docs/sphinx/source/wiki/Players.rst
Normal file
121
docs/sphinx/source/wiki/Players.rst
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
<wiki:toc max\_depth
|
||||
|
||||
"3" />
|
||||
======
|
||||
|
||||
Players=
|
||||
|
||||
All users (in the sense of actual people) connecting to Evennia are
|
||||
doing so through an object called *Player*. The Player object has no
|
||||
in-game representation; rather it is the out-of-character representation
|
||||
of the user. The Player object is what is chatting on
|
||||
`Channels <Communications.html>`_. It is also a good place to store
|
||||
`Permissions <Locks.html>`_ to be consistent between different in-game
|
||||
characters, configuration options, account info and other things related
|
||||
to the user. Players are `TypeClassed <Typeclasses.html>`_ entities and
|
||||
can store a `CmdSet <Commands.html>`_ of their own for OOC-type
|
||||
commands.
|
||||
|
||||
If you are logged in into default Evennia, you can use the ``@ooc``
|
||||
command to leave your current `Character <Objects.html>`_ and go into
|
||||
OOC mode. You are quite limited in this mode, basically it works like a
|
||||
simple chat program. It acts as a staging area for switching between
|
||||
Characters (if your game supports that) or as a safety mode if your
|
||||
Character gets deleted. . Use ``@ic`` to switch back "into" your
|
||||
character. Also note that the Player object can have a different set of
|
||||
`Permissions <Locks#Permissions.html>`_ from the Character they control
|
||||
(in the first character you create permissions for Player and Character
|
||||
are the same, however).
|
||||
|
||||
How to create your own Player types
|
||||
-----------------------------------
|
||||
|
||||
You will usually not want more than one Player typeclass for all new
|
||||
players (but you could in principle create a system that changes a
|
||||
player's typeclass dynamically).
|
||||
|
||||
An Evennia Player is, per definition, a Python class that includes
|
||||
``src.players.player.Player`` among its parents (if you are aware of how
|
||||
`Typeclasses <Typeclasses.html>`_ work, this is a typeclass linked to
|
||||
the ``PlayerDB`` database model). There is no equivalence to this in the
|
||||
``game/gamesrc`` folder, you need to inherit from the base object
|
||||
directly.
|
||||
|
||||
Here's how to define a new Player typeclass in code:
|
||||
|
||||
::
|
||||
|
||||
from src.players.player import Playerclass ConfigPlayer(Player): """ This creates a Player with some configuration options """ at_player_creation(self): "this is called only once, when player is first created" self.db.real_name = None # this is set later self.db.real_address = None # '' self.db.config_1 = True # default config self.db.config_2 = False # " self.db.config_3 = 1 # " # ... whatever our game needs to know
|
||||
|
||||
There is no pre-made folder in ``game/gamesrc`` to store custom player
|
||||
typeclasses. Either make your own folder or store it in
|
||||
``gamesrc/objects`` (remember that if you make your own folder you need
|
||||
to add an empty ``__init__.py`` file so that you can import the file
|
||||
later). To change which object becomes the Player object for new
|
||||
players, set the variable ``BASE_PLAYER_TYPECLASS`` in your
|
||||
``settings.py`` file.
|
||||
|
||||
Properties on Players
|
||||
---------------------
|
||||
|
||||
Beyond those properties assigned to all typeclassed objects (see
|
||||
`Typeclasses <Typeclasses.html>`_), the Player also has the following
|
||||
custom properties:
|
||||
|
||||
- ``user`` - a unique link to a ``User`` Django object, representing
|
||||
the logged-in user.
|
||||
- ``character`` - a reference to an associated *Character*-type
|
||||
`Object <Objects.html>`_.
|
||||
- ``obj`` - an alias for ``character``.
|
||||
- ``name`` - an alias for ``user.username``
|
||||
- ``sessions`` - a list of all connected Sessions (physical
|
||||
connections) this object listens to.
|
||||
- ``is_superuser`` (bool: True/False) - if this player is a superuser.
|
||||
|
||||
Special handlers:
|
||||
|
||||
- ``cmdset`` - This holds all the current `Commands <Commands.html>`_
|
||||
of this Player. By default these are the commands found in the cmdset
|
||||
defined by ``settings.CMDSET_OOC``.
|
||||
- ``nicks`` - This stores and handles `Nicks <Nicks.html>`_, in the
|
||||
same way as nicks it works on Objects. For Players, nicks are
|
||||
primarily used to store custom aliases for
|
||||
`Channels <Communications#Channels.html>`_.
|
||||
|
||||
How it all hangs together
|
||||
-------------------------
|
||||
|
||||
Looking at the above list, it's clear there are more to ``Player``s than
|
||||
what first meets the eye.
|
||||
|
||||
What happens when a person connects to Evennia and logs in is that they
|
||||
log in as a ``User`` object. This is a Django object that knows all
|
||||
about keeping track of authentication - it stores the login name
|
||||
(``username``), password, e-mail etc.
|
||||
|
||||
We can't change ``User`` very much unless we want to start digging down
|
||||
into Django source code (and we don't). Django however allows another
|
||||
model (technically called a *profile*) to reference the User for
|
||||
customization. This is our ``Player`` object. There is a one-to-one
|
||||
relationship between ``User`` and Player, so we have tried to completely
|
||||
hide the ``User`` interface throughout Evennia and left you to only have
|
||||
to deal with ``Player``.
|
||||
|
||||
So for all purposes, ``Player`` represents the OOC existence of a person
|
||||
logged into Evennia. You e.g. connect to
|
||||
`Channels <Communications.html>`_ using your Player identity. The Player
|
||||
object may store configurations and follows you wherever you go. You
|
||||
will however never see the Player object in-game. This is handled by a
|
||||
*Character*, a type of `Object <Objects.html>`_ connected to the
|
||||
``character`` property in the list above.
|
||||
|
||||
So why don't we just use ``Player`` to walk around with too? The main
|
||||
reason for this is flexibility. Your Player object won't change, but
|
||||
your character *might*. By separating the two you could easily implement
|
||||
a game where you can ``swap`` between different *Character* objects. All
|
||||
you'd need to do is change the ``character`` property to point to
|
||||
another suitable object (and change the values of the ``player``
|
||||
property on the affected objects).
|
||||
|
||||
So the structure looks like ``User - Player - Character``, where the
|
||||
last two are typeclassed, customizable objects.
|
||||
61
docs/sphinx/source/wiki/PortalAndServer.rst
Normal file
61
docs/sphinx/source/wiki/PortalAndServer.rst
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
Portal and Server layout
|
||||
========================
|
||||
|
||||
Evennia consists of two processes, known as *Portal* and *Server*. They
|
||||
can be controlled from inside the game or from the command line as
|
||||
described `here <StartStopReload.html>`_.
|
||||
|
||||
https://2498159658166209538-a-1802744773732722657-s-sites.googlegroups.com/site/evenniaserver/file-cabinet/evennia*server*portal.png
|
||||
|
||||
As seen above, the Server and Portal are glued together via an AMP
|
||||
(Asynchronous Messaging Protocol) connection. This allows the two
|
||||
programs to communicate.
|
||||
|
||||
Portal and Server Sessions
|
||||
--------------------------
|
||||
|
||||
*note: This is not really necessary to understand if you are new to
|
||||
Evennia.*
|
||||
|
||||
New Player connections are listened for and handled by the Portal using
|
||||
the `protocols <SessionProtocols.html>`_ it understands (such as telnet,
|
||||
ssh, webclient etc). When a new connection is established, a *Portal
|
||||
Session* is created on the Portal side. This session object looks
|
||||
different depending on which protocol is used to connect, but all still
|
||||
have a minimum set of attributes that are generic to all sessions.
|
||||
|
||||
These common properties are piped through AMP to the Server, who is now
|
||||
informed a new connection has been established. On the Server side, a
|
||||
*Server Session* object is created to represent this. There is only one
|
||||
type of Server Session. It looks the same regardless of how the Player
|
||||
connects, it leaves such details up to the Portal.
|
||||
|
||||
From now on, there is a one-to-one match between the Server Session on
|
||||
one side and the Portal Session on the other. Data arriving to the
|
||||
Portal Session is sent on to its mirror Server session and vice versa.
|
||||
|
||||
During certain situations, the portal- and server-side sessions are
|
||||
"synced" with each other:
|
||||
|
||||
- The Player closes their client, killing the Portal Session. The
|
||||
Portal syncs with the Server to make sure the corresponding Server
|
||||
Session is also deleted.
|
||||
- The Player quits from inside the game, killing the Server Session.
|
||||
The Server then syncs with the Portal to make sure to close the
|
||||
Portal connection cleanly.
|
||||
- The Server is rebooted/reset/shutdown - The Server Sessions are then
|
||||
copied over ("saved") to the Portal side. When the Server comes back
|
||||
up, this data is returned by the Portal so the two are again in sync.
|
||||
This way a Player's login status and other connection-critical things
|
||||
can survive a server reboot (assuming the Portal is also not stopped,
|
||||
obviously).
|
||||
|
||||
Sessionhandlers
|
||||
---------------
|
||||
|
||||
Both the Portal and Server each have a *sessionhandler* to manage the
|
||||
connections. These handlers contain all methods for relaying data across
|
||||
the AMP bridge. All types of Sessions hold a reference to their
|
||||
respective Sessionhandler (the property is called ``sessionhandler``) so
|
||||
they can relay data. See `protocols <SessionProtocols.html>`_ for more
|
||||
info on building new protocols.
|
||||
115
docs/sphinx/source/wiki/RemovingColour.rst
Normal file
115
docs/sphinx/source/wiki/RemovingColour.rst
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
Tutorial: Removing colour from your game
|
||||
========================================
|
||||
|
||||
This is a small tutorial for customizing your character objects, using
|
||||
the example of letting users turn on and off ansii colour parsing.
|
||||
|
||||
In the Building guide's `Colours <Colours.html>`_ page you can learn how
|
||||
to add Colour to your game by using special markup. Colours enhance the
|
||||
gaming experience, but not all users want colour. Examples would be
|
||||
users working from clients that don't support colour, or people with
|
||||
various seeing disabilities that rely on screen readers to play your
|
||||
game.
|
||||
|
||||
So here's how to allow those users to remove colour. It basically means
|
||||
you implementing a simple configuration system for your characters. This
|
||||
is the basic sequence:
|
||||
|
||||
#. Define your own default character typeclass, inheriting from
|
||||
Evennia's default.
|
||||
#. Set an attribute on the character to control markup on/off.
|
||||
#. Set your custom character class to be the default for new players.
|
||||
#. Overload the ``msg()`` method on the typeclass and change how it uses
|
||||
markup.
|
||||
#. Create a custom command to allow users to change their setting.
|
||||
|
||||
Setting up a custom Typeclass
|
||||
-----------------------------
|
||||
|
||||
Create a new module in ``game/gamesrc/objects`` named, for example,
|
||||
``mycharacter.py``.
|
||||
|
||||
In your new module, create a new `typeclass <Typeclasses.html>`_
|
||||
inheriting from ``game.gamesrc.objects.baseobjecs.Character``.
|
||||
|
||||
::
|
||||
|
||||
from game.gamesrc.objects.baseobjects import Characterclass ColourableCharacter(Character): at_object_creation(self): # set a colour config value self.db.config_colour = True
|
||||
|
||||
Above we set a simple config value as an `attribute <Attributes.html>`_.
|
||||
|
||||
Let's make sure that new characters are created of this type. Edit your
|
||||
``game/settings.py`` file and change ``BASE_CHARACTER_TYPECLASS`` to
|
||||
point to your new character class. Observe that this will only affect
|
||||
*new* characters, not those already created. You have to convert already
|
||||
created characters to the new typeclass by using the ``@typeclass``
|
||||
command (try on a secondary character first though, to test that
|
||||
everything works - you don't want to render your root user unusable!).
|
||||
|
||||
::
|
||||
|
||||
@typeclass/reset/force mycharacter.ColourableCharacter
|
||||
|
||||
The ``/reset`` switch clears all attributes and properties back to the
|
||||
default for the new typeclass and forces the object to re-run all its
|
||||
creation hooks (important in this case). ``/force`` might be needed if
|
||||
you edit the typeclass and want to update the object despite the actual
|
||||
typeclass name not having changed.
|
||||
|
||||
Overload the ``msg()`` method
|
||||
-----------------------------
|
||||
|
||||
Next we need to overload the ``msg()`` method. What we want is to check
|
||||
the configuration value before calling the main function. The original
|
||||
``msg`` method is found on ``src.objects.models.ObjectDB`` and is called
|
||||
like this:
|
||||
|
||||
::
|
||||
|
||||
msg(message, from_obj=None, data=None)
|
||||
|
||||
As long as we define a method on our custom object with the same name
|
||||
and keep the same number of arguments/keywords we will overload the
|
||||
original. Here's how it could look:
|
||||
|
||||
::
|
||||
|
||||
from src.utils import ansimsg(self, message, from_obj=None, data=None): "our custom msg()" if not self.db.config_colour: message = ansi.parse_ansi(message, strip_ansi=True) self.dbobj.msg(message, from_obj, data)
|
||||
|
||||
Above we create a custom version of the ``msg()`` method that cleans all
|
||||
ansi characters if the config value is not set to True. Once that's
|
||||
done, we pass it all on to the normal ``msg()`` on the database object
|
||||
(``ObjectDB``) to do its thing.
|
||||
|
||||
Since we put this custom ``msg()`` in our typeclass
|
||||
``ColourableCharacter``, it will be searched for and called rather than
|
||||
the default method on ``ObjectDB`` (which we now instead call manually).
|
||||
|
||||
There we go! Just flip the attribute ``config_colour`` to False and your
|
||||
users will not see any colour.
|
||||
|
||||
Custom colour config command
|
||||
----------------------------
|
||||
|
||||
For completeness, let's add a custom command so users can turn off their
|
||||
colour display themselves if they want.
|
||||
|
||||
In game/gamesrc/commands, create a new file, call it for example
|
||||
``configcmds.py`` (it's likely that you'll want to add other commands
|
||||
for configuration down the line).
|
||||
|
||||
::
|
||||
|
||||
from game.gamesrc.commands.basecommand import MuxCommandclass ConfigColourCmd(MuxCommand): """ Configures your colour Usage: @setcolour on|off This turns ansii-colours on/off. Default is on. """ key = "@setcolour" aliases = ["@setcolor"] def func(self): "Implements the command" if not self.args or not self.args in ("on", "off"): self.caller.msg("Usage: @setcolour on|off") return if self.args == "on": self.caller.db.config_colour = True else: self.caller.db.config_colour = False self.caller.msg("Colour was turned %s." % self.args)
|
||||
|
||||
Lastly, we make this command available to the user by adding it to the
|
||||
default command set. Easiest is to add it to the end of
|
||||
``DefaultCmdSet`` class in gamesrc/commands/basecmdset.py:
|
||||
|
||||
::
|
||||
|
||||
from game.gamesrc.commands import configcmds class DefaultCmdSet(cmdset_default.DefaultCmdSet): key = "DefaultMUX" def at_cmdset_creation(self): super(DefaultCmdSet, self).at_cmdset_creation() self.add(configcmds.ConfigColourCmd())
|
||||
|
||||
When adding a new command to a cmdset like this you need to run the
|
||||
``@reload`` command (or reboot the server). From here on out, your users
|
||||
should be able to turn on or off their colour as they please.
|
||||
160
docs/sphinx/source/wiki/Scripts.rst
Normal file
160
docs/sphinx/source/wiki/Scripts.rst
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
Scripts
|
||||
=======
|
||||
|
||||
*Scripts* are the way to implement everything in Evennia that may change
|
||||
with time.
|
||||
|
||||
The most obvious use of Scripts may be to use them as *timers* or
|
||||
*Events*. Consider a script running on the object ``Grandfather Clock``.
|
||||
The script has a timer that tells it to fire every hour. This allows the
|
||||
clock to chime regularly. The script might even regulate how often the
|
||||
clock must be rewound so it won't stop.
|
||||
|
||||
Scripts may act as changeable *States*. Consider for example creating a
|
||||
'dark' room. It has two scripts assigned on it - one ``DarkState``
|
||||
script, and one ``BrightState`` script. When characters enters the dark
|
||||
room, it assigns a custom `Cmdset <Commands.html>`_ to them - this
|
||||
command set (say) limits their actions because of the darkness. After
|
||||
the characters have stumbled around for a while, someone brings up a
|
||||
torch. As a light source is now in the room, ``DarkState`` reacts to
|
||||
this by shutting down itself and handing over control to the
|
||||
``BrightState`` script that restores normal commands. Finally, when the
|
||||
character with the torch leaves the room, the ``BrightState`` script
|
||||
detects this and obediently hands control back to the ``DarkState``,
|
||||
leaving the remaining poor characters in darkness once again.
|
||||
|
||||
By combining state-changes with timers one can make a room look
|
||||
different during nighttime than it does during the day. Weather and
|
||||
seasons might come and go. But one can also achieve more complex things
|
||||
such as state-AI systems that make mobs move around and possibly persue
|
||||
characters between rooms.
|
||||
|
||||
... In short, Scripts make the game world *tick*. Scripts are
|
||||
database-persistent objects and are `TypeClassed <Typeclasses.html>`_
|
||||
entities, with all the advantages that this entails.
|
||||
|
||||
How to create your own Script types
|
||||
-----------------------------------
|
||||
|
||||
An Evennia Script is, per definition, a Python class that includes
|
||||
``src.scripts.scripts.Script`` among its parents (if you are aware of
|
||||
how typeclasses work, this is a typeclass linked to the ``ScriptDB``
|
||||
database model). Scripts have no in-game representation and you cannot
|
||||
define them with any default commands. They have to be created in python
|
||||
code modules and imported from there into the game.
|
||||
|
||||
The vast majority of scripts are always run 'on'
|
||||
`Objects <Objects.html>`_ affecting that object and maybe its
|
||||
surroundings or contents. Scripts unrelated to objects are called
|
||||
*Global* scripts and could handle things like game-time, weather and
|
||||
other tickers.
|
||||
|
||||
Custom script modules are usually stored in ``game/gamesrc/scripts``. As
|
||||
a convenience you can inherit all scripts from
|
||||
``game.gamesrc.scripts.basescript.Script``.
|
||||
|
||||
You can try out scripts an add them to objects by use of the ``@script``
|
||||
command (not to the confused with ``@scripts`` which lists scripts). You
|
||||
can try it out with an example script:
|
||||
|
||||
::
|
||||
|
||||
> @script self = examples.bodyfunctions.BodyFunctions
|
||||
|
||||
This should cause some random messages. The ``/stop`` switch will kill
|
||||
the script again.
|
||||
|
||||
In code, you add scripts to `Objects <Objects.html>`_ and the script can
|
||||
then manipulate the object as desired. The script is added to the
|
||||
object's *script handler*, called simply ``scripts``. The handler takes
|
||||
care of all initialization and startup of the script for you.
|
||||
|
||||
::
|
||||
|
||||
# adding a script to an existing object 'myobj'myobj.scripts.add("game.gamesrc.scripts.myscripts.CoolScript")
|
||||
|
||||
The ``myobj.scripts.add()`` method also takes an argument *key* that
|
||||
allows you to name your script uniquely before adding it. This is not
|
||||
necessary, but is useful if you add many scripts of the same class and
|
||||
later plan to use ``myobj.scripts.delete`` to remove individual scripts.
|
||||
|
||||
Properties and functions defined on Scripts
|
||||
-------------------------------------------
|
||||
|
||||
It's important to know the variables controlling the script before one
|
||||
can create one. Beyond those properties assigned to all typeclassed
|
||||
objects (see `Typeclasses <Typeclasses.html>`_), such as ``key``,
|
||||
``db``, ``ndb`` etc, all Scripts also has the following properties:
|
||||
|
||||
- ``desc`` - an optional description of the script's function. Seen in
|
||||
listings.
|
||||
- ``interval`` - how often the script should run. If ``interval == 0``
|
||||
(default), it runs forever (it will not accept a negative value).
|
||||
- ``start_delay`` - (bool), if we should wait ``interval`` seconds
|
||||
before firing for the first time or not.
|
||||
- ``repeats`` - How many times we should repeat, assuming
|
||||
``interval > 0``. If repeats is set to ``<= 0``, the script will
|
||||
repeat indefinitely.
|
||||
- ``persistent``- if this script should survive a server reboot.
|
||||
|
||||
There is one special property:
|
||||
|
||||
- ``obj`` - the `Object <Objects.html>`_ this script is attached to (if
|
||||
any). You should not need to set this manually. If you add the script
|
||||
to the Object with ``myobj.scripts.add(myscriptpath)``, the ``obj``
|
||||
property will be set to ``myobj`` for you.
|
||||
|
||||
It's also imperative to know the hook functions. Normally, overriding
|
||||
these are all the customization you'll need to do in Scripts. You can
|
||||
find longer descriptions of these in ``gamesrc/scripts/basescript.py``.
|
||||
|
||||
- ``at_script_creation()`` - this is usually where the script class
|
||||
sets things like ``interval`` and ``repeats``; things that control
|
||||
how the script runs. It is only called once - when the script is
|
||||
first created.
|
||||
- ``is_valid()`` - determines if the script should still be running or
|
||||
not. This is called when running ``obj.scripts.validate()``, which
|
||||
you can run manually, but which also Evennia calls during certain
|
||||
situations such as reloads. This is also useful for using scripts as
|
||||
state managers. If the method returns ``False``, the script is
|
||||
stopped and cleanly removed.
|
||||
- ``at_start()`` - this is called when the script first starts. For
|
||||
persistent scripts this is at least once ever server startup. Note
|
||||
that this will *always* be called right away, also if ``start_delay``
|
||||
is ``True``.
|
||||
- ``at_repeat()`` - this is called every ``interval`` seconds, or not
|
||||
at all. It is called right away at startup, unless ``start_delay`` is
|
||||
``True``, in which case the system will wait ``interval`` seconds
|
||||
before calling.
|
||||
- ``at_stop()`` - this is called when the script stops for whatever
|
||||
reason. It's a good place to do custom cleanup.
|
||||
|
||||
::
|
||||
|
||||
import random
|
||||
from game.gamesrc.scripts.basescript import Scriptclass Weather(Script): "Displays weather info. Meant to be attached to a room." def at_script_creation(self): "Called once, during initial creation" self.key = "weather_script" self.desc = "Gives random weather messages." self.interval = 60 * 5 # every 5 minutes self.persistent = True self.at_repeat(self): "called every self.interval seconds." rand = random.random() if rand < 0.5: weather = "A faint breeze is felt." elif rand < 0.7: weather = "Clouds sweep across the sky." else: weather = "There is a light drizzle of rain." # send this message to everyone inside the object this # script is attached to (likely a room) self.obj.msg_contents(weather)
|
||||
|
||||
This is a simple weather script that we can put on an object. Every 5
|
||||
minutes it will tell everyone inside that object how the weather is.
|
||||
|
||||
To activate it, just add it to the script handler (``scripts``) on an
|
||||
`Room <Objects.html>`_. That object becomes ``self.obj`` in the example
|
||||
above. Here we put it on a room called ``myroom``:
|
||||
|
||||
::
|
||||
|
||||
# Assuming Script is found in game/gamesrc/scripts/weather.pymyroom.scripts.add(weather.Weather)
|
||||
|
||||
Or, from in-game, use the ``@script`` command:
|
||||
|
||||
::
|
||||
|
||||
@script here = weather.Weather
|
||||
|
||||
Further notes
|
||||
-------------
|
||||
|
||||
Should you *really* need to create a script unrelated to a particular
|
||||
Object (this is called a *Global* script), you can create it with
|
||||
``src.utils.create.create_script()`` and refrain from supplying an
|
||||
object to store it on. See that module for more info.
|
||||
103
docs/sphinx/source/wiki/SessionProtocols.rst
Normal file
103
docs/sphinx/source/wiki/SessionProtocols.rst
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
Portal Sessions and Protocols
|
||||
=============================
|
||||
|
||||
*Note: This is considered an advanced topic and not relevant to most
|
||||
users.*
|
||||
|
||||
A *Portal Session* is the basic data object representing an external
|
||||
connection to the Evennia `Portal <PortalAndServer.html>`_ -- usually a
|
||||
human player running a mud client of some kind. The way they connect -
|
||||
the language the player's client and Evennia use to talk to each other -
|
||||
is called the connection *Protocol*. The most common such protocol for
|
||||
MUD:s is the *Telnet* protocol. All Portal Sessions are stored and
|
||||
managed by the Portal's *sessionhandler*.
|
||||
|
||||
It's technically sometimes hard to separate the concept of *Session*
|
||||
from the concept of *Protocol* since both depend heavily on the other.
|
||||
|
||||
Protocols and Sessions both belong in ``src/server/``, so adding new
|
||||
protocols is one of the rare situations where development needs to
|
||||
happen in ``src/`` (in fact, if you do add a new useful protocol,
|
||||
consider contacting Evennia devs so we can include it in the main
|
||||
Evennia distribution!).
|
||||
|
||||
Protocols
|
||||
---------
|
||||
|
||||
Writing a stable communication protocol from scratch is not something
|
||||
we'll cover here, it's no trivial task. The good news is that Twisted
|
||||
offers implementations of many common protocols, ready for adapting.
|
||||
|
||||
Writing a protocol implementation in Twisted usually involves creating a
|
||||
class inheriting from a suitable Twisted parent, then overloading the
|
||||
methods that particular protocol requires so that it talks to Evennia.
|
||||
Whenever a new connection is made via this protocol, an instance of this
|
||||
class will be called. As various states change, specific-named methods
|
||||
on the class will be called (what they are named depends on the Twisted
|
||||
implementation).
|
||||
|
||||
A straight-forward protocol (like Telnet) is assumed to at least have
|
||||
the following components (although the actual method names might vary):
|
||||
|
||||
- ``connectionMade`` - called when a new connection is made. This must
|
||||
call ``self.init_session()`` with three arguments: an identifier for
|
||||
the protocol type (e.g. the string 'telnet'), the IP address
|
||||
connecting, and a reference to the sessionhandler.
|
||||
- ``connectionLost`` - called when connection is dropped for whatever
|
||||
reason. This must call 'self.sessionhandler.disconnect(self)' so the
|
||||
handler can make sure the disconnect is reported to the rest of the
|
||||
system.
|
||||
- ``getData`` - data arriving from the player to Evennia. This should
|
||||
apply whatever custom formatting this protocol needs, then relay the
|
||||
data to ``self.sessionhandler.data_in(self, msg, data)``.
|
||||
- sendLine - data from server to Player. This is called by hook
|
||||
``data_out()`` below.
|
||||
|
||||
See an example of this in
|
||||
`server/telnet.py <http://code.google.com/p/evennia/source/browse/trunk/src/server/telnet.py>`_.
|
||||
|
||||
These might not be as clear-cut in all protocols, but the principle is
|
||||
there. These four basic components - however they are accessed - links
|
||||
to the *Session*, which is the actual common interface between the
|
||||
different low-level protocols and Evennia.
|
||||
|
||||
Portal Sessions
|
||||
---------------
|
||||
|
||||
A *Portal Session* is an Evennia-specific thing. It must be a class
|
||||
inheriting from ``src.server.session.Session``. If you read the Telnet
|
||||
example above, the Protocol and Session are infact sometimes
|
||||
conveniently implemented in the same class through multiple inheritance.
|
||||
At startup the Portal creates and adds the Portal Session to its
|
||||
*sessionhandler*. While doing so, the session also gets assigned a
|
||||
property ``sessionhandler`` that refers to that very handler. This is
|
||||
important since the handler holds all methods relevant for sending and
|
||||
receiving data to and from the Server.
|
||||
|
||||
Whereas we don't know the method names of a Twisted Protocol (this can
|
||||
vary from protocol to protocol), the Session has a strict naming scheme
|
||||
that may not change; it is the glue that connects the Protocol to
|
||||
Evennia (along with some other convenient features).
|
||||
|
||||
The Session class must implement the following method hooks (which must
|
||||
be named exactly like this):
|
||||
|
||||
- ``disconnect()`` - called when manually disconnecting. Must call the
|
||||
protocol-specific disconnect method (e.g. ``connectionLost`` above)
|
||||
- ``data_out(string="", data=None)`` - data from Evennia to player.
|
||||
``string`` is normally a raw text string with formatting. ``data``
|
||||
can be a collection of any extra information the server want to give
|
||||
to the protocol; it's completely up to the Protocol to handle this
|
||||
(e.g. telnet completely ignores the ``data`` variable). From inside
|
||||
Evennia, this if often called with the alias ``msg`` instead. This
|
||||
method should call the protocol-specific send method, such as
|
||||
``self.sendLine()``, directly.
|
||||
|
||||
Assorted notes
|
||||
--------------
|
||||
|
||||
To take two examples, Evennia supports the *telnet* protocol as well as
|
||||
*webclient*, a custom ajax protocol. You'll find that whereas telnet is
|
||||
a textbook example of a Twisted protocol as seen above, the ajax client
|
||||
protocol looks quite different due to how it interacts with the
|
||||
webserver through long-polling (comet) style requests.
|
||||
123
docs/sphinx/source/wiki/SoftCode.rst
Normal file
123
docs/sphinx/source/wiki/SoftCode.rst
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
A brief explanation of what MUSH softcode is and why we use Python
|
||||
instead.
|
||||
|
||||
On MUX and Softcode: A brief overview
|
||||
=====================================
|
||||
|
||||
Evennia was originally created in order to provide a MUX/MUSH-style
|
||||
development environment without the kludgery of softcode. Although it
|
||||
has since grown to be adaptable to any style of MU``*`` it still ships
|
||||
with 'MUX-like' default commands.
|
||||
|
||||
This document will provide a quick overview of what softcode is, why it
|
||||
drove us to write Evennia, and why we instead use Python.
|
||||
|
||||
Softcode is a very simple programming language that was created for
|
||||
in-game development on TinyMUD derivatives such as MUX, PennMUSH,
|
||||
TinyMUSH, and RhostMUSH. The idea is that by providing a stripped down,
|
||||
minimalistic language for in-game use, you can allow quick and easy
|
||||
building and game development to happen without having to learn C/C++.
|
||||
There is an added benefit of not having to have to hand out shell access
|
||||
to all developers, and permissions can be used to alleviate many
|
||||
security problems.
|
||||
|
||||
Writing and installing softcode is done through a MUD client. As is
|
||||
such, it is not a formatted language. Each softcode function is a single
|
||||
line of varying size. Some functions can be a half of a page long due to
|
||||
this, which is obviously not very readable. The lack of formatting is
|
||||
one of the big reasons Evennia exists today. Bigger projects tend to
|
||||
choke under their own weight after time unless your entire staff has a
|
||||
good understanding of functional programming practices.
|
||||
|
||||
Examples of Softcode
|
||||
--------------------
|
||||
|
||||
Here is a simple 'Hello World!' command:
|
||||
|
||||
::
|
||||
|
||||
@set me=HELLO_WORLD.C:$hello:@pemit %#=Hello World!
|
||||
|
||||
Pasting this into a MUX/MUSH and typing 'hello' will theoretically yield
|
||||
'Hello World!', assuming certain flags are not set on your player
|
||||
object.
|
||||
|
||||
Setting attributes is done via ``@set``. Softcode also allows the use of
|
||||
the ampersand (``&``) symbol. This shorter version looks like this:
|
||||
|
||||
::
|
||||
|
||||
&HELLO_WORLD.C me=$hello:@pemit %#=Hello World!
|
||||
|
||||
Perhaps I want to break the Hello World into an attribute which is
|
||||
retrieved when emitting:
|
||||
|
||||
::
|
||||
|
||||
&HELLO_VALUE.D me=Hello World &HELLO_WORLD.C me=$hello:@pemit %#=[v(HELLO_VALUE.D)]
|
||||
|
||||
The v() function returns the HELLO\_VALUE.D attribute on the object that
|
||||
the command resides (``me``, which is yourself in this case). This
|
||||
should yield the same output as the first example.
|
||||
|
||||
If you are still curious about how Softcode works, take a look at some
|
||||
external resources:
|
||||
|
||||
- http://www.tinymux.com/wiki/index.php/Softcode
|
||||
- http://www.duh.com/discordia/mushman/man2x1
|
||||
|
||||
Problems with Softcode
|
||||
----------------------
|
||||
|
||||
Softcode is excellent at what it was intended for: simple things. It is
|
||||
an incredible tool if used for its intended purposes - an interactive
|
||||
object, a room with ambiance, simple global commands, simple economies
|
||||
and coded systems. However, once you start to try to write something
|
||||
like a complex combat system or a higher end economy, you're likely to
|
||||
find yourself buried under a mountain of functions that span various
|
||||
objects and are of various length.
|
||||
|
||||
Not to mention, softcode is not an inherently fast language. It is not
|
||||
compiled, it is parsed with each calling of a function. While MUX and
|
||||
MUSH parsers have jumped light years ahead of where they were even seven
|
||||
or eight years ago, they can still stutter under the weight of the more
|
||||
complex systems if not designed properly.
|
||||
|
||||
Changing Times
|
||||
--------------
|
||||
|
||||
Now that starting text-based games is easy and an option for even the
|
||||
most technically inarticulate, new projects are a dime a dozen. People
|
||||
are starting new MUDs every day with varying levels of commitment and
|
||||
ability. Because of this shift from fewer, larger, well-staffed games to
|
||||
a bunch of small, one or two developer games, some of the benefit of
|
||||
softcode fades.
|
||||
|
||||
Softcode is great in that it allows a mid to large sized staff all work
|
||||
on the same game without stepping on one another's toes. As mentioned
|
||||
before, shell access is not necessary to develop a MUX or a MUSH.
|
||||
However, now that we are seeing a lot more small, one or two-man shops,
|
||||
the issue of shell access and stepping on each other's toes is a lot
|
||||
less.
|
||||
|
||||
Our Solution
|
||||
============
|
||||
|
||||
For the hobbyist who would like the option to use a full-featured
|
||||
language, we created Evennia. We are no longer bound to single lines of
|
||||
softcode. Game developers now have access to the entire library of
|
||||
Python modules out there in the wild. Our complex systems may be
|
||||
organized neatly into modules, sub-modules, or even broken out into
|
||||
entire Python packages.
|
||||
|
||||
So what is *not* included in Evennia is a MUX/MOO-like online player
|
||||
building system. Advanced coding and building in Evennia is primarily
|
||||
intended to be done outside the game, in full-fledged Python modules. We
|
||||
feel that with a small development team you are better off using a
|
||||
professional source-control system (svn, git, bazaar, mercurial etc)
|
||||
anyway.
|
||||
|
||||
There is of course nothing stopping you from adding very advanced online
|
||||
building commands to Evennia (or even re-implement MUX' softcode in
|
||||
Python should you be very ambitious), but at this time this is not
|
||||
something planned to come with he core distribution.
|
||||
155
docs/sphinx/source/wiki/StaffVersionControl.rst
Normal file
155
docs/sphinx/source/wiki/StaffVersionControl.rst
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
Using Version Control to collaboratively manage and develop a game
|
||||
==================================================================
|
||||
|
||||
*TODO: This page does not yet deal much with the specifics of access
|
||||
control and protocols used when allowing access to a remove repository.
|
||||
The example commands also lack proper testing!*
|
||||
|
||||
Using modern `version control
|
||||
software <http://en.wikipedia.org/wiki/Version_control>`_ is a powerful
|
||||
way for a small development team to collaborate on a MUD project. Not
|
||||
only will it help you keep track of your changes (and undo bad things
|
||||
you do), it will also help combine the efforts of many people into one
|
||||
joint place.
|
||||
|
||||
Evennia uses version control in the form of the program Subversion (SVN)
|
||||
to manage the entire project. It allows multiple coders to contribute
|
||||
without getting in each other's way. The same mechanic would work just
|
||||
as well on the next level - with several people collaborating to build
|
||||
and code a MUD.
|
||||
|
||||
This page uses the Python-based
|
||||
`Bazaar <http://bazaar.canonical.com/en/>`_ version control system as an
|
||||
example of how to manage your MUD project. There are many other options
|
||||
though, notably *GIT* or *Mercurial* are worth checking out if Bazaar is
|
||||
not your thing. We use Bazaar's command-line interface, but Bazaar also
|
||||
has a full graphical GUI called *Bazaar Explorer* that might make it
|
||||
easier for newbies to get their head around the concept of version
|
||||
control. We also cannot go into much detail here, please refer to the
|
||||
very good Bazaar manuals for more help.
|
||||
|
||||
Premise
|
||||
-------
|
||||
|
||||
Let's say you are the admin/owner of a new MUD initiative, based on
|
||||
Evennia. The whole project will primarily be hosted on your computer.
|
||||
You are doing this with a few good friends that will help you implement
|
||||
the actual game system. You also have a few Builders/Coders of varying
|
||||
skill to help with creating the game world. Apart from building through
|
||||
their MUD clients, you also want them to be able to submit
|
||||
build-batchfiles, small code snippets, custom typeclasses and scripts --
|
||||
without giving them full access to your custom-coded game source.
|
||||
|
||||
First you need to set up a `development environment for a single
|
||||
developer <BazaarDevel.html>`_. That link will also teach you the basics
|
||||
of using Bazaar. Return here when you are done.
|
||||
|
||||
You should by this point have a Bazaar repository *evennia* containing
|
||||
two branches, ``evennia-trunk`` and ``evennia-mygame``.
|
||||
|
||||
Collaborating with trusted coders
|
||||
---------------------------------
|
||||
|
||||
There are many ways to make your code base available to your fellow
|
||||
administrators/coders.
|
||||
|
||||
Branching remotely
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The absolutely easiest way is to have them use Bazaar to simply branch
|
||||
your ``evennia-mygame`` branch as if it was any other branch. To do this
|
||||
they need to set up their own repository first with
|
||||
|
||||
``bzr init-repo``
|
||||
|
||||
Then they branch normally, but over the net:
|
||||
|
||||
``bzr branch sftp://url.to.your.computer/evennia-mygame myworkcopy``
|
||||
|
||||
(This example uses sftp, but which protocol is used need to be setup and
|
||||
agreed on. You also need to check so you don't have a firewall blocking
|
||||
that protocol. The `Bazaar branching
|
||||
manual <http://doc.bazaar.canonical.com/bzr.2.2/en/user-guide/branching%3Ci%3Ea%3C/i%3Eproject.html>`_
|
||||
gives a lot more info.)
|
||||
|
||||
This will create their very own copy of the branch named ``myworkcopy``,
|
||||
which they can work on as if it was their own. They can commit changes
|
||||
to it etc without affecting you. To keep their branches up-to-date
|
||||
against your branch they need to do a *pull*:
|
||||
|
||||
``bzr pull sftp://url.to.your.computer/evennia-mygame``
|
||||
|
||||
When they are ready to merge back their changes into your branch, they
|
||||
need to do a *push*:
|
||||
|
||||
``bzr push sftp://url.to.your.computer/evennia-mygame``
|
||||
|
||||
SVN-like checkout
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
Another variant is to make a separate branch for your development
|
||||
effort, and make this a *checkin branch*. Let's call this branch
|
||||
*evennia-share*:
|
||||
|
||||
``bzr branch evennia-mygame evennia-share``
|
||||
|
||||
So far this is the same as ``evennia-mygame``. With the *bind* command
|
||||
you make this branch act as a centralized, SVN-like repository:
|
||||
|
||||
``bzr bind evennia-share``
|
||||
|
||||
From now on, people now use ``commit`` and ``update`` from this branch,
|
||||
and use ``checkout`` to retrieve their personal copy. In fact, users and
|
||||
contributors can relate to this in the same way you deal with the main
|
||||
Evennia repository, by setting up equivalents to ``evennia-trunk`` and
|
||||
``evennia-mygame``. You merge to and from it as usual.
|
||||
|
||||
Collaborating with limited access
|
||||
---------------------------------
|
||||
|
||||
Not everyone should (or need) to download your entire customized
|
||||
codebase (the contents of ``evennia-mygame``) just because they
|
||||
volunteered to build a region of your game, or is scripting a new
|
||||
object. And whereas some building can surely happen on-line through MUD
|
||||
commands, the power of Evennia lies in its Python scripting abilities.
|
||||
This means them sending you files of code one way or another. Using
|
||||
e-mail or other communication methods works, but can quickly be a hassle
|
||||
with many files of different versions.
|
||||
|
||||
There are many ways to resolve this with version control, the easiest
|
||||
might be to simply set aside an isolated place for them to upload their
|
||||
data to you.
|
||||
|
||||
You could have one branch for all builders (so they could collaborate
|
||||
amongst themselves), or create a completely independent branch for each
|
||||
builder:
|
||||
|
||||
``bzr init anna-builds``
|
||||
|
||||
``bzr init peter-builds``
|
||||
|
||||
You could for example copy example files / builder instructions etc in
|
||||
there as needed (``cp`` is a Linux/Unix command, use whatever method is
|
||||
suitable in your OS): ``cp instructions.txt anna-builds``
|
||||
|
||||
``bzr add anna-builds/instructions.txt``
|
||||
|
||||
``bzr commit``
|
||||
|
||||
You could also *bind* this branch
|
||||
|
||||
``bzr bind anna-builds``
|
||||
|
||||
so the builder in the future can simply use ``commit`` and ``update`` to
|
||||
get things in and out of their respective upload area (they'd probably
|
||||
not mind that they upload to your machine every time they make a
|
||||
commit).
|
||||
|
||||
You can in this way manually inspect submitted files before copying them
|
||||
into the main branch as desired, using ``bzr add`` to have Bazaar track
|
||||
them.
|
||||
|
||||
.. figure:: http://b.imagehost.org/0824/bazaar_repo2.png
|
||||
:align: center
|
||||
:alt:
|
||||
|
||||
102
docs/sphinx/source/wiki/StartStopReload.rst
Normal file
102
docs/sphinx/source/wiki/StartStopReload.rst
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
Running Evennia
|
||||
===============
|
||||
|
||||
You control Evennia from ``game/`` using the ``evennia.py`` program.
|
||||
Below are described the various management options. You can also start
|
||||
the program without any arguments or use the *menu* option to get a
|
||||
multiple-choice menu instead.
|
||||
|
||||
::
|
||||
|
||||
python evennia.py menu
|
||||
|
||||
Starting Evennia
|
||||
----------------
|
||||
|
||||
Evennia consists of two components, the Evennia `Server and
|
||||
Portal <ServerAndPortal.html>`_. Briefly, the *Server* is what is
|
||||
running the mud. It handles all game-specific things but don't care
|
||||
exactly how players connect, only that they have. The *Portal* is a
|
||||
gateway to which players connect. It knows everything about telnet, ssh,
|
||||
webclient protocols etc but very little about the game. Both are
|
||||
required for a functioning mud.
|
||||
|
||||
::
|
||||
|
||||
python evennia.py start
|
||||
|
||||
The above command automatically starts both Portal and Server at the
|
||||
same time, logging to the log files in ``game/log``.
|
||||
|
||||
If you rather see error messages etc directly in the terminal (useful
|
||||
for quickly debugging your code), you use the -i (interactive) flag:
|
||||
|
||||
::
|
||||
|
||||
python evennia.py -i start
|
||||
|
||||
This will start the *Server* in interactive mode. The Portal will
|
||||
continue to log to its log file. This is normally what you want unless
|
||||
you are debugging the Portal.
|
||||
|
||||
You can also start the two components one at a time.
|
||||
|
||||
::
|
||||
|
||||
python evennia.py start server python evennia.py start portal
|
||||
|
||||
Adding -i to either of these explicit commands will start that component
|
||||
in interactive mode so it logs to the terminal rather than to log file.
|
||||
|
||||
Reloading
|
||||
---------
|
||||
|
||||
The act of *reloading* means the *Server* program is shut down and then
|
||||
restarted again. In the default cmdset you initiate a reload by using
|
||||
the ``@reload`` command from inside the game. The game will be briefly
|
||||
paused for all players as the server comes back up (since they are all
|
||||
connected to the *Portal*, their connections are not lost).
|
||||
|
||||
Reloading is as close to a "warm reboot" you can get. It reinitializes
|
||||
all code of Evennia, but doesn't kill "persistent" scripts. It also
|
||||
calls ``at_server_reload()`` hooks on all objects so you can save
|
||||
eventual temporary properties you want.
|
||||
|
||||
You can also reload the server from outside the game (not available in
|
||||
Windows):
|
||||
|
||||
::
|
||||
|
||||
python evennia.py reload
|
||||
|
||||
Resetting
|
||||
---------
|
||||
|
||||
*Resetting* is the equivalent of a "cold reboot" of the server - it will
|
||||
restart but will behave as it if was fully shut down. You initiate a
|
||||
reset using the ``@reset`` command from inside the game. As with a
|
||||
reload, no players will be disconnected during a shutdown. It will
|
||||
however purge all non-persistent scripts and will call
|
||||
``at_server_shutdown()`` hooks. It can be a good way to clean unsafe
|
||||
scripts during development, for example.
|
||||
|
||||
A reset is equivalent to
|
||||
|
||||
::
|
||||
|
||||
python evennia.py stop server python evennia.py start server
|
||||
|
||||
Shutting down
|
||||
-------------
|
||||
|
||||
A full shutdown closes Evennia completely, both Server and Portal. All
|
||||
players will be booted and systems saved and turned off cleanly. From
|
||||
inside the game you initiate a shutdown with the ``@shutdown`` command.
|
||||
|
||||
From command line you do
|
||||
|
||||
::
|
||||
|
||||
python.py evennia.py stop
|
||||
|
||||
You will see messages of both Server and Portal closing down.
|
||||
61
docs/sphinx/source/wiki/TextEncodings.rst
Normal file
61
docs/sphinx/source/wiki/TextEncodings.rst
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
Introduction
|
||||
============
|
||||
|
||||
Text *byte encodings* describe how a string of text is actually stored
|
||||
in the computer - that is, the particular sequence of bytes used to
|
||||
represent the letters of your particular alphabet. A common encoding
|
||||
used in English-speaking languages is the *ASCII* encoding. This
|
||||
describes the letters in the English alphabet (Aa-Zz) as well as a bunch
|
||||
of special characters. For describing other character sets (such as that
|
||||
of other languages with other letters than English), sets with names
|
||||
such as *Latin-1*, *ISO-8859-3* and *ARMSCII-8* are used. There are
|
||||
hundreds of different byte encodings in use around the world.
|
||||
|
||||
In contrast to the byte encoding is the *unicode representation*. The
|
||||
unicode is an internationally agreed-upon table describing essentially
|
||||
all available letters you could ever want to print. Everything from
|
||||
English to Chinese alphabets and all in between. So what Evennia (as
|
||||
well as Python and Django) does is to store everything in Unicode
|
||||
internally, but then converts the data to one of the encodings whenever
|
||||
outputting data to the user.
|
||||
|
||||
The problem is that when receiving a string of bytes from a user it's
|
||||
impossible for Evennia to guess which encoding was used - it's just a
|
||||
bunch of bytes! Evennia must know the encoding in order to convert back
|
||||
and from the correct unicode representation.
|
||||
|
||||
How to customize encodings
|
||||
==========================
|
||||
|
||||
As long as you stick to the standard ASCII character set (which means
|
||||
the normal English characters, basically) you should not have to worry
|
||||
much about this section.
|
||||
|
||||
If you want to build your game in another language however, or expect
|
||||
your users to want to use special characters not in ASCII, you need to
|
||||
consider which encodings you want to support.
|
||||
|
||||
As mentioned, there are many, many byte-encodings used around the world.
|
||||
It should be clear at this point that Evennia can't guess but has to
|
||||
assume or somehow be told which encoding you want to use to communicate
|
||||
with the server. Basically the encoding used by your client must be the
|
||||
same encoding used by the server. This can be customized in two
|
||||
complementary ways.
|
||||
|
||||
#. Point users to the default ``@encoding`` command. This allows them to
|
||||
themselves set which encoding they (and their client of choice) uses.
|
||||
Whereas data will remain stored as unicode internally in Evennia, all
|
||||
data received from and sent to this particular player will be
|
||||
converted to the given format before transmitting.
|
||||
#. As a back-up, in case the user-set encoding translation is erroneous
|
||||
or fails in some other way, Evennia will fall back to trying with the
|
||||
names defined in the settings variable ``ENCODINGS``. This is a list
|
||||
of encoding names Evennia will try, in order, before giving up and
|
||||
giving an encoding error message.
|
||||
|
||||
Note that having to try several different encodings every input/output
|
||||
adds unneccesary overhead. Try to guess the most common encodings you
|
||||
players will use and make sure these are tried first. The International
|
||||
*UTF-8* encoding is what Evennia assumes by default (and also what
|
||||
Python/Django use normally). See the Wikipedia article
|
||||
`here <http://en.wikipedia.org/wiki/Text_encodings>`_ for more help.
|
||||
71
docs/sphinx/source/wiki/TutorialWorldIntroduction.rst
Normal file
71
docs/sphinx/source/wiki/TutorialWorldIntroduction.rst
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
Tutorial World Introduction
|
||||
===========================
|
||||
|
||||
The *Tutorial World* is, quite simply, a small example of Evennia usage
|
||||
for you to learn from. It's also a functioning (if small) game - a small
|
||||
single-player quest area with some 20 rooms that you can explore on your
|
||||
quest to find a mythical weapon.
|
||||
|
||||
The source code is fully documented and you can find the whole thing in
|
||||
``contrib/tutorial_world``.
|
||||
|
||||
Some features exemplified by the tutorial world:
|
||||
|
||||
- Tutorial command, giving "behind-the-scenes" help for every room and
|
||||
some of the special objects
|
||||
- Hidden exits
|
||||
- Objects with multiple custom interactions
|
||||
- Large-area rooms
|
||||
- Outdoor weather rooms
|
||||
- Dark room, needing light source
|
||||
- Puzzle object
|
||||
- Multi-room puzzle
|
||||
- Aggressive mobile with roam, pursue and battle state-engine AI
|
||||
- Weapons, also used by mobs
|
||||
- Simple combat system with attack/defend commands
|
||||
- Object spawn
|
||||
- Teleporter trap rooms
|
||||
|
||||
Install
|
||||
-------
|
||||
|
||||
The tutorial world consists of a a few modules in
|
||||
``contrib/tutorial_world/`` containing custom
|
||||
`Typeclasses <Typeclasses.html>`_ for `rooms and
|
||||
objects <Objects.html>`_, associated `commands <Commands.html>`_ and a
|
||||
few custom `scripts <Scripts.html>`_ to make things tick.
|
||||
|
||||
These reusable bits and pieces are then put together into a functioning
|
||||
game area ("world" is maybe too big a word for such a small zone) using
|
||||
a `batch script <BatchProcessors.html>`_ called ``build.ev``. To
|
||||
install, log into the server as the superuser (user #1) and run:
|
||||
|
||||
::
|
||||
|
||||
@batchcommand contrib.tutorial_world.build
|
||||
|
||||
The world will be built (there will be a lot of text output) and you
|
||||
will end up back in Limbo with a new exit called ``tutorial``. You can
|
||||
also use the ``/interactive`` switch of ``@batchcommand`` to be able to
|
||||
slowly go through each step of building the world in detail.
|
||||
|
||||
To play the tutorial "correctly", you should *not* do so as superuser.
|
||||
The reason for this is that many game systems ignore the presence of a
|
||||
superuser and will thus not work as normal. Create a new, non-superuser
|
||||
character instead (as superuser you can of course examine things "under
|
||||
the hood" later if you want).
|
||||
|
||||
Notes
|
||||
-----
|
||||
|
||||
When reading and learning from the code, keep in mind that *Tutorial
|
||||
World* was created with a very specific goal: to install easily and to
|
||||
not permanently modify the rest of the server. It therefore goes to some
|
||||
length to use only temporary solutions and to clean up after itself.
|
||||
None of the basic typeclasses are modified more than temporarily. This
|
||||
means the tutorial sometimes needs to solve things in a more complex
|
||||
fashion than really needed.
|
||||
|
||||
When coding your own game you'd of course not have such considerations -
|
||||
you'd just customize the base typeclasses to always work just the way
|
||||
you want and be done with it.
|
||||
251
docs/sphinx/source/wiki/Typeclasses.rst
Normal file
251
docs/sphinx/source/wiki/Typeclasses.rst
Normal file
|
|
@ -0,0 +1,251 @@
|
|||
Typeclassed objects
|
||||
===================
|
||||
|
||||
Several of the the main game 'entities' in Evennia, namely
|
||||
`Players <Players.html>`_, `Objects <Objects.html>`_ and
|
||||
`Scripts <Scripts.html>`_ - are what we call *typeclassed*. This
|
||||
basically means that they are almost normal Python classes that hide
|
||||
underlying database models ...
|
||||
|
||||
... and that's basically all you *really* need to know about how
|
||||
typeclasses work behind the scenes. To work with them you should know
|
||||
that all the listed game entities inherit a common interface from the
|
||||
typeclass system, properties you can *always* expect a typeclassed
|
||||
entity to have *beyond* the more specialized properties unique to each
|
||||
sub-type. Typeclasses also do some special things with their in-built
|
||||
class methods that you shouldn't edit.
|
||||
|
||||
Properties available to all typeclassed entities (Players, Objects,
|
||||
Scripts)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- ``key`` - the main identifier for the entity, say 'Rose', 'myscript'
|
||||
or 'Paul'. ``name`` is an alias that can also be used.
|
||||
- ``date_created`` - time stamp when this object was created.
|
||||
- ``locks`` - the `lockhandler <Locks.html>`_ that manages access
|
||||
restrictsions. Use locks.add(), locks.get() etc.
|
||||
- ``dbref`` - the database id (database ref) of the object. This is a
|
||||
unique integer. You can usually also use ``id``.
|
||||
|
||||
There are three further properties that warrant special mention:
|
||||
|
||||
- ``db`` (!DataBase) - this is the interface to the `Attribute
|
||||
system <Attributes.html>`_, allowing for *persistently* storing your
|
||||
own custom data on the entity (i.e. data that will survive a server
|
||||
restart).
|
||||
- ``ndb`` (!NotDataBase) - this is equivalent to the functionality of
|
||||
``db`` but is used to store *non-peristent* data (i.e. data that will
|
||||
be lost on server restart).
|
||||
- ``dbobj`` - this is a reference to the *Database object* connected to
|
||||
this typeclass (reversely, ``dbobj.typeclass`` is a reference back to
|
||||
this very typeclass).
|
||||
|
||||
Each of the typeclassed entities then extend this list with their own
|
||||
properties. Go to the pages for `Objects <Objects.html>`_,
|
||||
`Scripts <Scripts.html>`_ and `Players <Players.html>`_ respectively for
|
||||
more info.
|
||||
|
||||
Things to remember when using TypeClasses
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Typeclasses mostly behave like normal Python classes - you can
|
||||
add/overload custom methods and inherit your own classes from them -
|
||||
most things you'd expect to be able to do with a Python class. There are
|
||||
a few things that you need to remember however:
|
||||
|
||||
- Evennia will look for and call especially named *hook methods* on the
|
||||
typeclass in different situations. Just define a new method on the
|
||||
class named correctly and Evennia will call it appropriately. Hooks
|
||||
are your main way to interact with the server. Available hook methods
|
||||
are listed in the resepective base modules in ``game/gamesrc/``.
|
||||
- Don't use the normal ``__init__()`` to set up your typeclass. It is
|
||||
used by Evennia to set up the mechanics of the Typeclass system. Use
|
||||
the designated hook method instead, such as ``at_object_creation()``,
|
||||
``at_player_creation()`` or ``at_script_creation()``.
|
||||
- Don't re-implement the python special class methods
|
||||
``__setattr__()``, ``__getattribute__()`` and ``__delattr__()``.
|
||||
These are used extensively by the Typeclass system.
|
||||
- Some property names cannot be assigned to a Typeclassed entity due to
|
||||
being used for internal Typeclass operations. If you try, you will
|
||||
get an error. These property names are *id*, *dbobj*, *db*, *ndb*,
|
||||
*objects*, *typeclass*, *attr*, *save* and *delete*.
|
||||
- Even if they are not explicitly protected, you should not redefine
|
||||
the "type" of the default typeclass properties listed above and on
|
||||
each typeclassed entity (such as trying to store an integer in the
|
||||
``key`` property). These properties are often called by the engine
|
||||
expecting a certain type of return, and some are even tied directly
|
||||
to the database and will thus return errors if given a value of the
|
||||
wrong type.
|
||||
- *Advanced note*: If you are doing advanced coding you might (very
|
||||
rarely) find that overloading ``__init__``, ``_setattr__`` etc allows
|
||||
for some functionality not possible with hooks alone. You *can* do it
|
||||
if you know what you are doing, but you *must* then remember to use
|
||||
Python's built-in function ``super()`` to call the parent method too,
|
||||
or you *will* crash the server! You have been warned.
|
||||
|
||||
How typeclasses actually work
|
||||
-----------------------------
|
||||
|
||||
\_You don't need to read this section to use typeclassed entities, but
|
||||
it might be useful if you want to do advanced things or are interested
|
||||
in knowing how Evennia actually does things behind the scenes.\_
|
||||
|
||||
All typeclassed entities actually consist of two (three) parts:
|
||||
|
||||
#. The *Typeclass* (a normal Python class with customized get/set
|
||||
behaviour)
|
||||
#. The *Database model* (Django model)
|
||||
#. (`Attributes <Attributes.html>`_)
|
||||
|
||||
The *Typeclass* is an almost normal Python class, and holds all the
|
||||
flexibility of such a class. This is what makes the class special, some
|
||||
of which was already mentioned above:
|
||||
|
||||
- It inherits from ``src.typeclasses.typeclass.TypeClass``.
|
||||
- ``__init__()`` is reserved for various custom startup procedures.
|
||||
- It always initiates a property ``dbobj`` that points to a *Database
|
||||
model*.
|
||||
- It redefines python's normal ``__getattribute__()``,
|
||||
``__setattr__()`` and ``__delattr__`` on itself to relay all data on
|
||||
itself to/from ``dbobj`` (i.e. to/from the database model).
|
||||
|
||||
The related *Database model* in turn communicates data in and out of the
|
||||
the database. The Database model holds the following (typeclass-related)
|
||||
features:
|
||||
|
||||
- It inherits from ``src.typeclasses.models.TypedObject`` (this
|
||||
actually implements a
|
||||
`idmapper <http://github.com/dcramer/django-idmapper>`_-type model.
|
||||
If that doesn't mean anything to you, never mind).
|
||||
- It has a field ``typelclass_path`` that gives the python path to the
|
||||
*Typeclass* associated with this particular model instance.
|
||||
- It has a property *typeclass* that dynamically imports and loads the
|
||||
*Typeclass* from ``typeclass_path``, and assigns itself to the
|
||||
Typeclass' ``dbobj`` property.
|
||||
- It redefines ``__getattribute__()`` to search its typeclass too,
|
||||
while avoiding loops. This means you can search either object and
|
||||
find also data stored on the other.
|
||||
|
||||
The *Attributes* are not really part of the typeclass scheme, but are
|
||||
very important for saving data without having to change the database
|
||||
object itself. They are covered in a separate entry
|
||||
`here <Attributes.html>`_.
|
||||
|
||||
Why split it like this?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The *Database model* (Django model) allows for saving data to the
|
||||
database and is a great place for storing persistent data an object
|
||||
might need during and between sessions. But it is not suitable for
|
||||
representing all the various objects a game needs. You *don't* want to
|
||||
have to redefine a new database representation just because a
|
||||
``CarObject`` needs to look and behave differently than a
|
||||
``ChairObject``. So instead we keep the database model pretty "generic",
|
||||
and only put database Fields on it that we know that *all* objects would
|
||||
need (or that require fast and regular database searches). Examples of
|
||||
such fields are "key" and "location".
|
||||
|
||||
Enter the *Typeclass*. For lack of a better word, a typeclass
|
||||
"decorates" a Django database model. Through the re-definition of the
|
||||
class' get/set methods, the typeclass constantly communicates behind the
|
||||
scenes with the Django model. The beauty of it is that this is all
|
||||
hidden from you, the coder. As long as you don't overwrite the few magic
|
||||
methods listed above you can deal with the typeclass almost as you would
|
||||
any normal Python class. You can extend it, inherit from it, and so on,
|
||||
mostly without caring that it is infact hiding a full persistent
|
||||
database representation. So you can now create a typeclass-class
|
||||
*Flowers* and then inherit a bunch of other typeclass-classes from that
|
||||
one, like *Rose*, *Tulip*, *Sunflower*. As your classes are instantiated
|
||||
they will each secretly carry a reference to a database model to which
|
||||
all data *actually* goes. We, however, can treat the two as if they
|
||||
where one.
|
||||
|
||||
Below is a schematic of the database/typeclass structure.
|
||||
|
||||
.. figure:: http://d.imagehost.org/0784/typeclasses1.png
|
||||
:align: center
|
||||
:alt:
|
||||
Let's see how object creation looks like in an example.
|
||||
|
||||
#. We have defined a Typeclass called *Rose* in
|
||||
``game.gamesrc.objects.flower.Rose``. It inherits from
|
||||
``game.gamesrc.objects.baseobjects.Object``, which is a grandchild of
|
||||
``src.typeclasses.typeclass.TypeClass``. So the rose a typeclassed
|
||||
object, just as it should be.
|
||||
#. Using a command we create a new *Rose* instance *!RedRose* (e.g. with
|
||||
``@create redrose:flowers.Rose``).
|
||||
#. A new database model is created and given the key *!RedRose*. Since
|
||||
this is an `Object <Objects.html>`_ typeclass (rather than a Script
|
||||
or Player), the database model used is
|
||||
``src.objects.models.ObjectDB``, which inherits directly from
|
||||
``src.typeclasses.models.TypedObject``).
|
||||
#. This new Django-model instance receives the python-path to the *Rose*
|
||||
typeclass and stores it as a string on itself (in a database field
|
||||
``typeclass_path``). When the server restarts in the future, the
|
||||
database model will restart from this point.
|
||||
#. The database model next *imports* the Typeclass from its stored path
|
||||
and creates a new instance of it in memory. It stores a reference to
|
||||
this instance of *Rose* (*!RedRose*)in a property called
|
||||
``typeclass``.
|
||||
#. As *Rose* is instantiated, its ``__init__()`` method is called. What
|
||||
this does it to make sure to store the back-reference to the Django
|
||||
model on our new *Rose* instance. This back-reference is called
|
||||
``dbobj``.
|
||||
#. The creation method next runs the relevant startup hooks on the
|
||||
typeclass, such as ``at_object_creation()``.
|
||||
|
||||
Storing properties on the typeclass-instance will in fact transparently
|
||||
save to the database object. So ``RedRose.thorns = True`` is the same as
|
||||
``RedRose.dbobj.thorns = True`` (note also that depending on your
|
||||
``FULL_PERSISTENCE`` setting, this may or may not save ``thorns`` as an
|
||||
`Attribute <Attributes.html>`_ behind the scenes).
|
||||
|
||||
Doing ``ouch = RedRose.thorns`` is however not really as symmetric. The
|
||||
system will in this case *first* check the Typeclass instance and only
|
||||
if no property *thorns* was found will go on to examine the database
|
||||
object. So ``ouch = RedRose.thorns`` is not necessarily the same as
|
||||
``ouch = RedRose.dbobj.thorns`` in this case. The reason we don't assume
|
||||
everything to be on the database object is that you are likely to
|
||||
customize your *Rose* typeclass with custom parameters and methods that
|
||||
are intended to *overload* the default methods on the database object.
|
||||
These are thus searched and run first, and you can then safely use
|
||||
``self.dbobj`` from the typeclass to call the original function if you
|
||||
want. An example of Typeclass overloading is found
|
||||
`here <CommandPrompt#Prompt%3Ci%3Eon%3C/i%3Ethe%3Ci%3Esame%3C/i%3Eline.html>`_.
|
||||
|
||||
Another example:
|
||||
|
||||
.. figure:: http://b.imagehost.org/0023/typeclasses2.png
|
||||
:align: center
|
||||
:alt:
|
||||
Caveats of the typeclass system
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
While there are many advantages to the typeclass system over working
|
||||
with Django models directly, there are also some caveats to remember.
|
||||
|
||||
Be careful when not using Evennia's search and create methods. Almost
|
||||
all code in evennia (including default commands) assume that what is
|
||||
returned from searches or creates are Typeclasses, not Django models
|
||||
(i.e. the first of the two in the pair). This is what you get if you use
|
||||
any of the model manager methods, and also the create/search functions
|
||||
in ``src.utils.create`` and ``src.utils.search``. Old Django-gurus will
|
||||
find it tempting to use Django's in-build database query methods, such
|
||||
as ``ObjectDB.objects.filter()`` to get data. This works, but the result
|
||||
will then of course *not* be a typeclass but a Django model object (a
|
||||
query). You can easily convert between them with ``dbobj.typeclass`` and
|
||||
``typeclass.dbobj``, but you should be aware of this distinction.
|
||||
|
||||
::
|
||||
|
||||
obj = ObjectDB.objects.get_id(1) # custom evennia manager method. This returns the typeclass. obj = ObjectDB.objects.get(1) # standard Django. Returns a Django model object.
|
||||
|
||||
Even more important to know for Django affectionados: Evennia's custom
|
||||
methods return *lists* where you with normal Django methods would expect
|
||||
``Query`` objects (e.g. from the ``filter()`` method). As long as you
|
||||
don't confuse what result type you are dealing with (for example you
|
||||
cannot 'link' ``list``s together the way you can ``Querysets``), you
|
||||
should be fine.
|
||||
|
||||
Read the ``manager.py`` files in each relevant folder under ``src/`` to
|
||||
see which database access methods are available.
|
||||
103
docs/sphinx/source/wiki/UnitTesting.rst
Normal file
103
docs/sphinx/source/wiki/UnitTesting.rst
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
Using and writing unit tests for Evennia.
|
||||
|
||||
Unit Testing
|
||||
============
|
||||
|
||||
*This topic is mainly of interest to people interested in helping to
|
||||
develop Evennia itself.*
|
||||
|
||||
Unit testing means testing components of a program in isolation from
|
||||
each other to make sure every part works on its own before using it with
|
||||
others. Extensive testing helps avoid new updates causing unexpected
|
||||
side effects as well as alleviates general code rot (a more
|
||||
comprehensive wikipedia article on unit testing can be found
|
||||
`here <http://en.wikipedia.org/wiki/Unit_test>`_).
|
||||
|
||||
A typical unit test calls some component of Evennia with a given input,
|
||||
looks at the result and makes sure that this result looks as expected.
|
||||
Rather than having lots of stand-alone test programs, Evennia makes use
|
||||
of a central *test runner*. This is a program that gathers all available
|
||||
tests all over the Evennia source code (called *test suites*) and runs
|
||||
them all in one go. Errors and tracebacks are reported.
|
||||
|
||||
Running the test suite
|
||||
----------------------
|
||||
|
||||
To run the Evennia test suite, go to the ``game/`` folder and issue the
|
||||
command
|
||||
|
||||
``python manage.py test``
|
||||
|
||||
A temporary database will be instantiated to manage the tests. If
|
||||
everything works out you will see how many tests were run and how long
|
||||
it took. If something went wrong you will get error messages.
|
||||
|
||||
Writing new tests
|
||||
-----------------
|
||||
|
||||
Evennia's test suite makes use of Django unit test system, which in turn
|
||||
relies on Python's *unittest* module. Evennia's test modules are always
|
||||
named ``tests.py`` and should be located in different sub folders of
|
||||
``src/`` depending on which system they are testing. You can find an
|
||||
example of a testing module in ``src/objects/tests.py``.
|
||||
|
||||
Inside the ``tests.py`` module you create classes inheriting from
|
||||
``django.test.TestCase`` (later versions of Django will use
|
||||
``django.utils.unittest.TestCase`` instead). A ``TestCase`` class is
|
||||
used to test a single aspect or component in various ways. Each test
|
||||
case contains one ore more *test methods* - these define the actual
|
||||
tests to run. You can name the test methods anything you want as long as
|
||||
the name starts with "``test_``". Your ``TestCase`` class can also have
|
||||
a method !SetUp(). This is run before each test, setting up whatever
|
||||
preparations the test methods need.
|
||||
|
||||
To test the results, you use special methods of the ``TestCase`` class.
|
||||
Many of those start with "``assert``", such as ``assertEqual`` or
|
||||
``assertTrue``.
|
||||
|
||||
Example of a ``TestCase`` class (inside a file ``tests.py``):
|
||||
|
||||
::
|
||||
|
||||
# testing a simple funciontry: # this is an optimized version only available in later Django versions from django.utils.unittest import TestCase except ImportError: # if the first fail, we use the old version from django.test import TestCase# the function we want to test from mypath import myfuncTestObj(unittest.TestCase): "This tests a function myfunc." def test_return_value(self): "test method. Makes sure return value is as expected." expected_return = "This is me being nice." actual_return = myfunc() # test self.assertEqual(expected_return, actual_return) def test_alternative_call(self): "test method. Calls with a keyword argument." expected_return = "This is me being baaaad." actual_return = myfunc(bad=True) # test self.assertEqual(expected_return, actual_return)
|
||||
|
||||
The above example is very simplistic, but you should get the idea. Look
|
||||
at ``src/objects/tests.py`` for more realistic examples of tests. You
|
||||
might also want to read the `documentation for the unittest
|
||||
module <http://docs.python.org/library/unittest.html>`_.
|
||||
|
||||
Testing in-game Commands
|
||||
------------------------
|
||||
|
||||
In-game Commands are a special case. Tests for the default commands are
|
||||
put in ``src/commands/default/tests.py``. This test suite is executed as
|
||||
part of running the ``objects`` test suite (since it lies outside
|
||||
Django's normal "app" structure). It also supplies a few convenience
|
||||
functions for executing commands (notably creating a "fake" player
|
||||
session so as to mimic an actual command call). It also makes several
|
||||
test characters and objects available. For example ``char1`` is a
|
||||
"logged in" Character object that acts as the one calling the command.
|
||||
|
||||
Each command tested should have its own ``TestCase`` class. Inherit this
|
||||
class from the ``CommandTest`` class in the same module to get access to
|
||||
the command-specific utilities mentioned.
|
||||
|
||||
::
|
||||
|
||||
class TestSet(CommandTest):
|
||||
"tests the @set command by simple call"
|
||||
def test_call(self):
|
||||
self.execute_command("@set self/testval = mytestvalue")
|
||||
# knowing what @set does, our test character (char1) should
|
||||
# by now have a new attribute 'testval' with the value 'mytestvalue'.
|
||||
self.assertEqual("mytestvalue", self.char1.db.testval)
|
||||
|
||||
A note on adding new tests
|
||||
--------------------------
|
||||
|
||||
Having an extensive tests suite is very important for avoiding code
|
||||
degradation as Evennia is developed. Only a small fraction of the
|
||||
Evennia codebase is covered by test suites at this point. Writing new
|
||||
tests is not hard, it's more a matter of finding the time to do so. So
|
||||
adding new tests is really an area where everyone can contribute, also
|
||||
with only limited Python skills.
|
||||
61
docs/sphinx/source/wiki/UpdatingYourGame.rst
Normal file
61
docs/sphinx/source/wiki/UpdatingYourGame.rst
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
Updating your Game
|
||||
==================
|
||||
|
||||
Fortunately, it's extremely easy to keep your Evennia server up-to-date
|
||||
via Subversion. If you haven't already, see the `Getting Started
|
||||
guide <GettingStarted.html>`_ and get your installation up. You'll then
|
||||
want to join the `Evennia Commit
|
||||
Log <http://groups.google.com/group/evennia-commits/>`_ group. This will
|
||||
notify you via email whenever updates are made to the source in the
|
||||
Subversion repository, letting you know you need to update. You can also
|
||||
subscribe to the RSS feed or check up on the feeds from
|
||||
`http://www.evennia.com. <http://www.evennia.com.>`_ When you're wanting
|
||||
to apply updates, simply ``cd`` to your ``evennia`` root directory and
|
||||
type:
|
||||
|
||||
``svn update``
|
||||
|
||||
Assuming you've got the command line client. If you're using a graphical
|
||||
client, you will probably want to navigate to the ``evennia`` directory
|
||||
and either right click and find your client's update function, or use
|
||||
one of the menus (if applicable).
|
||||
|
||||
You can review the latest changes with
|
||||
|
||||
``svn log``
|
||||
|
||||
or the equivalent in the graphical client. You can also see the latest
|
||||
changes online `here <http://code.google.com/p/evennia/source/list>`_.
|
||||
|
||||
A Note on Schema Migration
|
||||
--------------------------
|
||||
|
||||
Database migration becomes an issue when/if the database models of
|
||||
Evennia changes in an update (this should be gradually more and more
|
||||
rare as Evennia matures). If you already have a database, this then has
|
||||
to be updated to match the latest server version or you are likely to
|
||||
run into trouble down the line.
|
||||
|
||||
One way to solve this is to manually add/remove the new tables or fields
|
||||
to your existing database (or simply reset your database if you don't
|
||||
have anything important in it yet). Enter
|
||||
`South <http://south.aeracode.org/>`_. South is a Django database schema
|
||||
migration tool. It keep tracks of changes in the database schema and
|
||||
applies those changes to the database for you.
|
||||
|
||||
Using South is optional, but if you install South, Evennia will use it
|
||||
automatically. See correct section of
|
||||
`GettingStarted <GettingStarted.html>`_ on how to install South and the
|
||||
slightly changed way to start a clean database server when South is used
|
||||
(you have to give the ``mange.py migrate`` command as well as
|
||||
``manage.py syncdb``).
|
||||
|
||||
Once you have a database ready to use South, you work as normal.
|
||||
Whenever a new Evennia update tells you that the database schema has
|
||||
changed (check ``svn log`` or the online list), you go to ``game/`` and
|
||||
run this command:
|
||||
|
||||
``python manage.py migrate``
|
||||
|
||||
This will convert your database to the new schema and you should be set
|
||||
to go.
|
||||
48
docs/sphinx/source/wiki/UsingMUXAsAStandard.rst
Normal file
48
docs/sphinx/source/wiki/UsingMUXAsAStandard.rst
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
The 'MUX-like' default of Evennia
|
||||
=================================
|
||||
|
||||
Evennia is a highly customizable codebase. Among many things, its
|
||||
command structure and indeed the very way that commands look can all be
|
||||
changed by you. If you like the way, say, DikuMUDs handle things, you
|
||||
could emulate that with Evennia. Or LPMuds, or MOOs. Or if you are
|
||||
ambitious you could design a whole new style, perfectly fitting your own
|
||||
dreams of the ideal MUD.
|
||||
|
||||
We do offer a default however. The default Evennia setup tend to
|
||||
resemble `MUX2 <http://www.tinymux.org/>`_, and its cousins
|
||||
`PennMUSH <http://www.pennmush.org>`_,
|
||||
`TinyMUSH <http://tinymush.sourceforge.net/>`_, and
|
||||
`RhostMUSH <http://www.rhostmush.org/>`_. By default we emulate these
|
||||
Tiny derivatives (MUX2, Penn, etc) in the user interface and building
|
||||
commands. We believe these codebases have found a good way to do things
|
||||
in terms of building and administration. We hope this will also make it
|
||||
more familiar for new users coming from those communities to start using
|
||||
Evennia.
|
||||
|
||||
However, Evennia has taken a completely different stance on how admins
|
||||
extend and improve their games. Instead of implementing a special
|
||||
in-game language (!SoftCode), all game extension is done through Python
|
||||
modules, like the rest of Evennia. This gives the admin practically
|
||||
unlimited power to extend the game leveraging the full power of a mature
|
||||
high level programming language. You can find a more elaborate
|
||||
discussion about our take on MUX SoftCode `here <SoftCode.html>`_.
|
||||
|
||||
WWMD - What Would MUX Do?
|
||||
-------------------------
|
||||
|
||||
Our policy for implementing the default commands is as follows - we tend
|
||||
to look at MUX2's implementation before contriving one of our own. This
|
||||
comes with a caveat though - there are many cases where this is
|
||||
impossible without sacrificing the usability and utility of the
|
||||
codebase. In those cases, differences in implementation as well as
|
||||
command syntax is to be expected. Evennia is *not* MUX - we handle all
|
||||
underlying systems very differently and don't use SoftCode. The WWMD
|
||||
policy is only applied to the default commands, not to any other
|
||||
programming paradigms in the codebase.
|
||||
|
||||
If you are an Evennia codebase developer, consider activating
|
||||
``IMPORT_MUX_HELP`` in your ``settings.py`` file. This will import a
|
||||
copy of the MUX2 help database and might come in handy when it comes to
|
||||
adding/implementing new default commands. If you must deviate from
|
||||
MUX2's implementation of something, make sure to document it extensively
|
||||
in the command's docstring.
|
||||
64
docs/sphinx/source/wiki/WebFeatures.rst
Normal file
64
docs/sphinx/source/wiki/WebFeatures.rst
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
Web Features
|
||||
============
|
||||
|
||||
Evennia is its own webserver and hosts a default website and browser
|
||||
webclient.
|
||||
|
||||
Editing the Web site
|
||||
--------------------
|
||||
|
||||
The Evennia website is a Django application that ties in with the MUD
|
||||
database. It allows you to, for example, tell website visitors how many
|
||||
players are logged into the game at the moment, how long the server has
|
||||
been up and any other database information you may want. The dynamic
|
||||
website application is located in ``src/web/website`` whereas you will
|
||||
find the html files in ``src/web/templates/prosimii``. Static media such
|
||||
as images, css and javascript files are served from ``src/web/media``.
|
||||
|
||||
You can access the website during development by going to
|
||||
``http://localhost:8000``.
|
||||
|
||||
Since it's not recommended to edit files in ``src/`` directly, we need
|
||||
to devise a way to allow website customization from ``game/gamesrc``.
|
||||
This is not really finalized at the current time (it will be easier to
|
||||
share media directories in Django 1.3) so for now, your easiest course
|
||||
of action is probably to copy the entire ``src/web`` directory into
|
||||
``game/gamesrc/`` and modify the copy. Make sure to retain permissions
|
||||
so the server can access the directory.
|
||||
|
||||
You also need to modify the settings file. Set ``ROOT_URLCONF`` to your
|
||||
new ``game.gamesrc.web.urls`` and add an entry
|
||||
``os.path.join(GAME_DIR, "web", "templates", ACTIVE_TEMPLATE)`` to the
|
||||
``TEMPLATE_DIRS`` tuple. You should now have a separate website setup
|
||||
you can edit as you like. Be aware that updates we do to ``src/web``
|
||||
will not transfer automatically to your copy, so you'll need to apply
|
||||
updates manually.
|
||||
|
||||
Web client
|
||||
----------
|
||||
|
||||
Evennia comes with a MUD client accessible from a normal web browser. It
|
||||
is technically a javascript client polling an asynchronous webserver
|
||||
through long-polling (this is also known as a *COMET* setup). The
|
||||
webclient server is defined in ``src/server/webclient`` and is not
|
||||
something that should normally need to be edited unless you are creating
|
||||
a custom client. The client javascript, html and css files are located
|
||||
under the respective folders of ``src/web/``.
|
||||
|
||||
The webclient uses the `jQuery <http://jquery.com/>`_ javascript
|
||||
library. This is imported automatically over the internet when running
|
||||
the server. If you want to run the client without an internet
|
||||
connection, you need to download the library from the jQuery homepage
|
||||
and put it in ``src/web/media/javascript``. Then edit
|
||||
``src/web/templates/prosimii/webclient.html`` and uncomment the line:
|
||||
|
||||
::
|
||||
|
||||
<script src="/media/javascript/jquery-1.4.4.js" type="text/javascript" charset="utf-8"></script>
|
||||
|
||||
(edit it to match the name of the ``*.js`` for the jQuery version you
|
||||
downloaded).
|
||||
|
||||
The webclient requires the webserver to be running and is then found on
|
||||
``http://localhost:8000/webclient``. For now it's best to follow the
|
||||
procedure suggested in the previous section if you want to customize it.
|
||||
127
docs/sphinx/source/wiki/Workshop.rst
Normal file
127
docs/sphinx/source/wiki/Workshop.rst
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
rtclient protocol
|
||||
=================
|
||||
|
||||
*Note: Most functionality of a webcliebnt implementation is already
|
||||
added to trunk as of Nov 2010. That implementation does however not use
|
||||
a custom protocol as suggested below. Rather it parses telnet-formatted
|
||||
ansi text and converts it to html. Custom client operations (such as
|
||||
opening windows or other features not relevant to telnet or other
|
||||
protocols) should instead eb handled by a second "data" object being
|
||||
passed to the server through the msg() method.*
|
||||
|
||||
rtclient is an extended and bastardized telnet protocol that processes
|
||||
html and javascript embedded in the telnet session.
|
||||
|
||||
rtclient is implemented by the Teltola client, a web-based html/js
|
||||
telnet client that is being integrated with Evennia and is written in
|
||||
twisted/python.
|
||||
|
||||
There are two principle aspects to the rtclient protocol, mode control
|
||||
and buffering.
|
||||
|
||||
modes
|
||||
-----
|
||||
|
||||
Unencoded Mode
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
All output is buffered until ascii char 10, 13, or 255 is encountered or
|
||||
the mode changes or no output has been added to the buffer in the last
|
||||
1/10th second and the buffer is not blank. When this occurs, the client
|
||||
interprets the entire buffer as plain text and flushes the buffer.
|
||||
|
||||
HTML Mode
|
||||
~~~~~~~~~
|
||||
|
||||
All output is buffered. When the mode changes, the client then parses
|
||||
the entire buffer as HTML.
|
||||
|
||||
Javascript Mode
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
All output is buffered. When the mode changes, the client then parses
|
||||
the entire buffer as Javascript.
|
||||
|
||||
Sample Sessions
|
||||
---------------
|
||||
|
||||
# start html mode, send html, force buffer flush
|
||||
|
||||
::
|
||||
|
||||
session.msg(chr(240) + "<h1>Test</h1>" + chr(242) + chr(244))
|
||||
|
||||
# same as above, but realize that msg sends end-of-line # automatically
|
||||
thus sending the buffer via AUTO\_CHNK
|
||||
|
||||
::
|
||||
|
||||
session.msg(chr(240) + "<h1>Test</h1>" + chr(242))
|
||||
|
||||
# more elaborate example sending javascript, html, and unbuffered text #
|
||||
note we are using the tokens imported instead of the constants
|
||||
|
||||
::
|
||||
|
||||
from game.gamesrc.teltola.RTClient import HTML_TOKEN, JAVASCRIPT_TOKEN, UNENCODED_TOKEN
|
||||
hello_world_js = "alert('hello world');"
|
||||
welcome_html = "<h1>Hello World</h1>"
|
||||
session.msg("".join([JAVASCRIPT_TOKEN, hello_world_js, HTML_TOKEN, welcome_html, UNENCODED_TOKEN,"Hello there."]))
|
||||
|
||||
::
|
||||
|
||||
session.msg(chr(243))
|
||||
session.msg(my_text_with_line_breaks)
|
||||
session.msg(chr(244))
|
||||
|
||||
Values of Tokens
|
||||
----------------
|
||||
|
||||
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| chr() value \| name \| function |
|
||||
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| 240 \| HTMLTOKEN \| lets client know it is about to receive HTML |
|
||||
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| 241 \| JAVASCRIPTTOKEN \| lets client know it is about to receive javascript |
|
||||
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| 242 \| UNENCODEDTOKEN \| lets client know it is about to receive plain telnet text |
|
||||
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| 243 \| NOAUTOCHUNKTOKEN \| applies to unencoded mode only, prevents the chunking of text at end-of-line characters so that only mode changes force the buffer to be sent to the client |
|
||||
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| 244 \| AUTOCHUNKTOKEN \| applies to unencoded mode only, enables automatic chunking of text by end-of-line characters and by non-blank buffers not having been written to in the last 1/10th second |
|
||||
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
|
||||
identifying as an rtclient
|
||||
--------------------------
|
||||
|
||||
rtclients send the text rtclient\\n immediately after connection so that
|
||||
the server may enable rtclient extensions
|
||||
|
||||
Buffering Control
|
||||
-----------------
|
||||
|
||||
Unbuffered output is not supported. There are two different buffering
|
||||
methods supported. The default method is called AUTOCHUNK and applies
|
||||
only to unencoded data (see data encoding section below). JAVASCRIPT and
|
||||
HTML data is always treated as NO\_AUTOCHUNK.
|
||||
|
||||
NO\_AUTOCHUNK
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
Contents are never sent to the client until the encoding mode changes
|
||||
(for example, switching from HTML to UNENCODED will send the HTML
|
||||
buffer) or the buffering mode changes (for example, one could set
|
||||
NO*AUTOCHUNK, send some text, and set NO*AUTOCHUNK again to force a
|
||||
flush.
|
||||
|
||||
AUTOCHUNK
|
||||
~~~~~~~~~
|
||||
|
||||
It sends the buffer to the client as unencoded text whenever one of two
|
||||
things happen: \* the buffer is non-blank but hasn't had anything added
|
||||
to it very recently (about 1/10th of a second) \* the buffer ends with
|
||||
an end-of-line character (10, 13, 255)
|
||||
|
||||
Autochunking strips end-of-line characters and the client adds in its
|
||||
own EOL! If you would like to preserve them, send them from within
|
||||
NO\_AUTOCHUNK.
|
||||
294
docs/sphinx/source/wiki/WorkshopDefaultGame.rst
Normal file
294
docs/sphinx/source/wiki/WorkshopDefaultGame.rst
Normal file
|
|
@ -0,0 +1,294 @@
|
|||
Workshop: Default-game whitepage
|
||||
|
||||
<wiki:toc max\_depth
|
||||
|
||||
"3" />
|
||||
======
|
||||
|
||||
Introduction =
|
||||
|
||||
This is an initiative to create a "base" game system to be shipped with
|
||||
Evennia in a "contrib" folder. The game is an independent
|
||||
re-implementation of the basic stuff of the
|
||||
`SMAUG <http://www.smaug.org>`_ system. No code from the original will
|
||||
be used, and no licensed content will be included in the release. For
|
||||
easy testing of content, rcaskey's SMAUG importer will be used.
|
||||
|
||||
TODO, first prototype
|
||||
=====================
|
||||
|
||||
The first stage serves to establish a prototype implementation -
|
||||
something that shows the parts hanging together, but with only a subset
|
||||
of the functionality.
|
||||
|
||||
Create custom `TypeClasses <Objects.html>`_ supporting the SMAUG system:
|
||||
|
||||
- Object->!SmaugObject->!SmaugBeing->!SmaugCharacter,Character
|
||||
- Object->!SmaugObject->!SmaugBeing->!SmaugMob-> ...
|
||||
- Object->!SmaugObject->!SmaugThing-> ...
|
||||
|
||||
Create limited subclasses or attributes on objects
|
||||
|
||||
- Limited classes/races (1-2?)
|
||||
- Skills (<lvl 5?) - not too many!
|
||||
|
||||
Behind-the-scenes SMAUG engine
|
||||
|
||||
- Contest resolution
|
||||
- Mobs moving around, "AI"
|
||||
- Base combat system
|
||||
|
||||
Import of small data set, testing.
|
||||
|
||||
SMAUG specifics
|
||||
===============
|
||||
|
||||
Code Availability By Lvl
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
+-------+---------------------------+
|
||||
| Lvl | Code Bit |
|
||||
+-------+---------------------------+
|
||||
| 0 | spell*disenchant*weapon |
|
||||
+-------+---------------------------+
|
||||
| 1 | spell*cause*light |
|
||||
+-------+---------------------------+
|
||||
| 1 | dohide |
|
||||
+-------+---------------------------+
|
||||
| 1 | spellventriloquate |
|
||||
+-------+---------------------------+
|
||||
| 1 | docook |
|
||||
+-------+---------------------------+
|
||||
| 1 | doclimb |
|
||||
+-------+---------------------------+
|
||||
| 1 | spellnull |
|
||||
+-------+---------------------------+
|
||||
| 1 | dopick |
|
||||
+-------+---------------------------+
|
||||
| 1 | dosteal |
|
||||
+-------+---------------------------+
|
||||
| 1 | dobackstab |
|
||||
+-------+---------------------------+
|
||||
| 1 | spellsmaug |
|
||||
+-------+---------------------------+
|
||||
| 1 | dokick |
|
||||
+-------+---------------------------+
|
||||
| 2 | dodig |
|
||||
+-------+---------------------------+
|
||||
| 2 | domount |
|
||||
+-------+---------------------------+
|
||||
| 2 | spell*faerie*fire |
|
||||
+-------+---------------------------+
|
||||
| 2 | spell*create*food |
|
||||
+-------+---------------------------+
|
||||
| 2 | spell*create*water |
|
||||
+-------+---------------------------+
|
||||
| 2 | spellweaken |
|
||||
+-------+---------------------------+
|
||||
| 2 | spellblackhand |
|
||||
+-------+---------------------------+
|
||||
| 3 | doscan |
|
||||
+-------+---------------------------+
|
||||
| 3 | dosearch |
|
||||
+-------+---------------------------+
|
||||
| 3 | dofeed |
|
||||
+-------+---------------------------+
|
||||
| 3 | spell*chill*touch |
|
||||
+-------+---------------------------+
|
||||
| 4 | dorescue |
|
||||
+-------+---------------------------+
|
||||
| 4 | spellcureblindness |
|
||||
+-------+---------------------------+
|
||||
| 4 | spellinvis |
|
||||
+-------+---------------------------+
|
||||
| 4 | doaid |
|
||||
+-------+---------------------------+
|
||||
| 4 | spellgalvanicwhip |
|
||||
+-------+---------------------------+
|
||||
| 5 | spellblindness |
|
||||
+-------+---------------------------+
|
||||
| 5 | spell*cause*serious |
|
||||
+-------+---------------------------+
|
||||
| 5 | spell*detect*poison |
|
||||
+-------+---------------------------+
|
||||
| 5 | spell*burning*hands |
|
||||
+-------+---------------------------+
|
||||
| 5 | spell*know*alignment |
|
||||
+-------+---------------------------+
|
||||
| 6 | spell*locate*object |
|
||||
+-------+---------------------------+
|
||||
| 6 | dotrack |
|
||||
+-------+---------------------------+
|
||||
| 6 | spellremoveinvis |
|
||||
+-------+---------------------------+
|
||||
| 6 | spellpoison |
|
||||
+-------+---------------------------+
|
||||
| 7 | spellearthquake |
|
||||
+-------+---------------------------+
|
||||
| 7 | spellshockinggrasp |
|
||||
+-------+---------------------------+
|
||||
| 8 | spellteleport |
|
||||
+-------+---------------------------+
|
||||
| 8 | dobashdoor |
|
||||
+-------+---------------------------+
|
||||
| 8 | spellsummon |
|
||||
+-------+---------------------------+
|
||||
| 8 | spell*cure*poison |
|
||||
+-------+---------------------------+
|
||||
| 8 | spelldisruption |
|
||||
+-------+---------------------------+
|
||||
| 9 | spellbethsaideantouch |
|
||||
+-------+---------------------------+
|
||||
| 9 | spellcausecritical |
|
||||
+-------+---------------------------+
|
||||
| 9 | spelllightningbolt |
|
||||
+-------+---------------------------+
|
||||
| 10 | spellidentify |
|
||||
+-------+---------------------------+
|
||||
| 10 | spell*faerie*fog |
|
||||
+-------+---------------------------+
|
||||
| 10 | spell*control*weather |
|
||||
+-------+---------------------------+
|
||||
| 10 | spell*dispel*evil |
|
||||
+-------+---------------------------+
|
||||
| 10 | dodisarm |
|
||||
+-------+---------------------------+
|
||||
| 11 | spellcolourspray |
|
||||
+-------+---------------------------+
|
||||
| 11 | dobite |
|
||||
+-------+---------------------------+
|
||||
| 11 | spell*dispel*magic |
|
||||
+-------+---------------------------+
|
||||
| 11 | dobloodlet |
|
||||
+-------+---------------------------+
|
||||
| 12 | spellsleep |
|
||||
+-------+---------------------------+
|
||||
| 12 | spellcurse |
|
||||
+-------+---------------------------+
|
||||
| 12 | spellcalllightning |
|
||||
+-------+---------------------------+
|
||||
| 12 | spellremovecurse |
|
||||
+-------+---------------------------+
|
||||
| 12 | spellenchantweapon |
|
||||
+-------+---------------------------+
|
||||
| 12 | spellword*of*recall |
|
||||
+-------+---------------------------+
|
||||
| 13 | spellharm |
|
||||
+-------+---------------------------+
|
||||
| 13 | spellfireball |
|
||||
+-------+---------------------------+
|
||||
| 13 | spellexpurgation |
|
||||
+-------+---------------------------+
|
||||
| 13 | spellflamestrike |
|
||||
+-------+---------------------------+
|
||||
| 13 | spell*midas*touch |
|
||||
+-------+---------------------------+
|
||||
| 13 | spell*energy*drain |
|
||||
+-------+---------------------------+
|
||||
| 14 | spell*spectral*furor |
|
||||
+-------+---------------------------+
|
||||
| 14 | spell*charm*person |
|
||||
+-------+---------------------------+
|
||||
| 15 | spell*remove*trap |
|
||||
+-------+---------------------------+
|
||||
| 16 | spellfarsight |
|
||||
+-------+---------------------------+
|
||||
| 16 | dodetrap |
|
||||
+-------+---------------------------+
|
||||
| 17 | spelltransport |
|
||||
+-------+---------------------------+
|
||||
| 17 | spelldream |
|
||||
+-------+---------------------------+
|
||||
| 18 | spell*sulfurous*spray |
|
||||
+-------+---------------------------+
|
||||
| 18 | spell*pass*door |
|
||||
+-------+---------------------------+
|
||||
| 19 | spell*sonic*resonance |
|
||||
+-------+---------------------------+
|
||||
| 20 | dogouge |
|
||||
+-------+---------------------------+
|
||||
| 20 | spellacidblast |
|
||||
+-------+---------------------------+
|
||||
| 21 | spellportal |
|
||||
+-------+---------------------------+
|
||||
| 23 | spell*black*fist |
|
||||
+-------+---------------------------+
|
||||
| 25 | dopunch |
|
||||
+-------+---------------------------+
|
||||
| 25 | docircle |
|
||||
+-------+---------------------------+
|
||||
| 25 | dobrew |
|
||||
+-------+---------------------------+
|
||||
| 27 | spellmagneticthrust |
|
||||
+-------+---------------------------+
|
||||
| 27 | dopoisonweapon |
|
||||
+-------+---------------------------+
|
||||
| 28 | spellscorchingsurge |
|
||||
+-------+---------------------------+
|
||||
| 30 | doscribe |
|
||||
+-------+---------------------------+
|
||||
| 30 | dobash |
|
||||
+-------+---------------------------+
|
||||
| 30 | spellastralwalk |
|
||||
+-------+---------------------------+
|
||||
| 31 | domistwalk |
|
||||
+-------+---------------------------+
|
||||
| 32 | spell*ethereal*fist |
|
||||
+-------+---------------------------+
|
||||
| 32 | spellknock |
|
||||
+-------+---------------------------+
|
||||
| 33 | spellrecharge |
|
||||
+-------+---------------------------+
|
||||
| 34 | spell*caustic*fount |
|
||||
+-------+---------------------------+
|
||||
| 35 | spell*sacral*divinity |
|
||||
+-------+---------------------------+
|
||||
| 35 | spell*plant*pass |
|
||||
+-------+---------------------------+
|
||||
| 37 | spell*hand*ofchaos |
|
||||
+-------+---------------------------+
|
||||
| 37 | spellacetumprimus |
|
||||
+-------+---------------------------+
|
||||
| 39 | spellsolarflight |
|
||||
+-------+---------------------------+
|
||||
| 41 | dobroach |
|
||||
+-------+---------------------------+
|
||||
| 41 | spell*frost*breath |
|
||||
+-------+---------------------------+
|
||||
| 42 | spell*helical*flow |
|
||||
+-------+---------------------------+
|
||||
| 42 | spell*animate*dead |
|
||||
+-------+---------------------------+
|
||||
| 42 | spell*lightning*breath |
|
||||
+-------+---------------------------+
|
||||
| 43 | spell*acid*breath |
|
||||
+-------+---------------------------+
|
||||
| 44 | spell*fire*breath |
|
||||
+-------+---------------------------+
|
||||
| 45 | spell*gas*breath |
|
||||
+-------+---------------------------+
|
||||
| 46 | spell*spiral*blast |
|
||||
+-------+---------------------------+
|
||||
| 46 | spell*black*lightning |
|
||||
+-------+---------------------------+
|
||||
| 48 | dostun |
|
||||
+-------+---------------------------+
|
||||
| 48 | spellquantumspike |
|
||||
+-------+---------------------------+
|
||||
| 50 | dohitall |
|
||||
+-------+---------------------------+
|
||||
| 51 | spellpossess |
|
||||
+-------+---------------------------+
|
||||
| 51 | spellchangesex |
|
||||
+-------+---------------------------+
|
||||
| 51 | spellgate |
|
||||
+-------+---------------------------+
|
||||
| 51 | doslice |
|
||||
+-------+---------------------------+
|
||||
| 51 | spellpolymorph |
|
||||
+-------+---------------------------+
|
||||
| 51 | do\_berserk |
|
||||
+-------+---------------------------+
|
||||
|
||||
+ the affects they apply float, sneak, hide, detect invisibility, detect
|
||||
magic, detect evil, invisibility
|
||||
64
docs/sphinx/src2rest/src2rest.py
Executable file
64
docs/sphinx/src2rest/src2rest.py
Executable file
|
|
@ -0,0 +1,64 @@
|
|||
#! /usr/bin/python
|
||||
#
|
||||
# Auto-generate reST documentation for Sphinx from Evennia source
|
||||
# code.
|
||||
#
|
||||
# Uses etinenned's sphinx autopackage script. Install it to folder
|
||||
# "autogen" in this same directory:
|
||||
#
|
||||
# hg clone https://bitbucket.org/etienned/sphinx-autopackage-script autogen
|
||||
#
|
||||
# Create a directory tree "code/" containing one directory for every
|
||||
# package in the PACKAGE dictionary below. Make sure EVENNIA_DIR
|
||||
# points to an Evennia root dir. Then just run this script. A new
|
||||
# folder sphinx/source/code will be created with the reST sources.
|
||||
#
|
||||
# Note - this is not working very well at the moment, not all sources
|
||||
# seems to be properly detected and you get lots of errors when
|
||||
# compiling. To nevertheless make a link to the code from the doc
|
||||
# front page, edit docs/sphinx/sources/index.rst to reference
|
||||
# code/modules.
|
||||
#
|
||||
|
||||
|
||||
import os, subprocess, shutil
|
||||
|
||||
EVENNIA_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
|
||||
SPHINX_DIR = os.path.join(os.path.join(EVENNIA_DIR, "docs"), "sphinx")
|
||||
SPHINX_SRC_DIR = os.path.join(SPHINX_DIR, "source")
|
||||
SPHINX_CODE_DIR = os.path.join(SPHINX_SRC_DIR, "code")
|
||||
|
||||
CONVERT_DIR = os.path.join(SPHINX_DIR, 'src2rest')
|
||||
AUTOGEN_EXE = os.path.join(CONVERT_DIR, os.path.join("autogen", "generate_modules.py"))
|
||||
|
||||
def src2rest():
|
||||
"""
|
||||
Run import
|
||||
"""
|
||||
try:
|
||||
shutil.rmtree(SPHINX_CODE_DIR)
|
||||
print "Emptied old %s." % SPHINX_CODE_DIR
|
||||
except OSError:
|
||||
pass
|
||||
os.mkdir(SPHINX_CODE_DIR)
|
||||
|
||||
inpath = EVENNIA_DIR
|
||||
outpath = SPHINX_CODE_DIR
|
||||
excludes = [r".*/migrations/.*", r"evennia\.py$", r"manage\.py$",
|
||||
r"runner\.py$", r"server.py$", r"portal.py$"]
|
||||
|
||||
subprocess.call(["python", AUTOGEN_EXE,
|
||||
"-n", "Evennia",
|
||||
"-d", outpath,
|
||||
"-s", "rst",
|
||||
"-f",
|
||||
inpath] + excludes)
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
try:
|
||||
src2rest()
|
||||
except Exception, e:
|
||||
print e
|
||||
print "Make sure to read the header of this file so that it's properly set up."
|
||||
109
docs/sphinx/wiki2rest/wiki2rest.py
Executable file
109
docs/sphinx/wiki2rest/wiki2rest.py
Executable file
|
|
@ -0,0 +1,109 @@
|
|||
#! /usr/bin/python
|
||||
#
|
||||
# Converts Evennia's google-style wiki pages to reST documents
|
||||
#
|
||||
# Setting up to run:
|
||||
#
|
||||
# 1) From this directory, use SVN to download wiki2html converter by Chris Roos. Make sure
|
||||
# to download into a directory "wiki2html" like this:
|
||||
#
|
||||
# svn co http://chrisroos.googlecode.com/svn/trunk/google-wiki-syntax wiki2html
|
||||
#
|
||||
# This is a ruby program! Sorry, it was the best match I could find to do this.
|
||||
# So if you don't have ruby, you need that too.
|
||||
#
|
||||
# 2) Install pandoc:
|
||||
#
|
||||
# apt-get install pandoc (debian)
|
||||
# or download from
|
||||
# http://johnmacfarlane.net/pandoc/
|
||||
#
|
||||
# 3) Retrieve wiki files (*.wiki) from Google code by mercurial. Make sure
|
||||
# to retrieve them into a directory wikiconvert/wiki:
|
||||
#
|
||||
# hg clone https://code.google.com/p/evennia/wiki wiki
|
||||
#
|
||||
# 4) Check so that you have the following file structure:
|
||||
#
|
||||
# wiki/ (containing google code wiki files)
|
||||
# wiki2html/ (containing the wiki_converter.rb ruby program.)
|
||||
# html/ (empty)
|
||||
# rest/ (empty)
|
||||
# (this file)
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
# 1) Pull the wiki files into wiki/ so you have the latest.
|
||||
# 2) Run wiki2rest.py. Folders html and rest will end up containing the conversions and the contents
|
||||
# of rest/ will automatically be copied over to docs/sphinx/source/wiki.
|
||||
#
|
||||
|
||||
import sys, os, subprocess, re
|
||||
|
||||
# Setup
|
||||
|
||||
EVENNIA_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
|
||||
|
||||
SPHINX_DIR = os.path.join(os.path.join(EVENNIA_DIR, "docs"), "sphinx")
|
||||
SPHINX_SRC_DIR = os.path.join(SPHINX_DIR, "source")
|
||||
SPHINX_WIKI_DIR = os.path.join(SPHINX_SRC_DIR, "wiki")
|
||||
CONVERT_DIR = os.path.join(SPHINX_DIR, "wiki2rest")
|
||||
|
||||
WIKI_DIR = os.path.join(CONVERT_DIR, "wiki")
|
||||
HTML_DIR = os.path.join(CONVERT_DIR, "html")
|
||||
REST_DIR = os.path.join(CONVERT_DIR, "rest")
|
||||
WIKI2HTML_DIR = os.path.join(CONVERT_DIR, "wiki2html")
|
||||
PANDOC_EXE = "pandoc"
|
||||
RUBY_EXE = "ruby"
|
||||
|
||||
# files to not convert (no file ending)
|
||||
NO_CONVERT = ["SideBar", "Screenshot"]
|
||||
|
||||
|
||||
def wiki2rest():
|
||||
"""
|
||||
Convert from wikifile to rst file, going through html
|
||||
"""
|
||||
# convert from wikifile to html with wiki2html
|
||||
subprocess.call([RUBY_EXE, "wiki_convertor.rb", WIKI_DIR, HTML_DIR], cwd=WIKI2HTML_DIR)
|
||||
|
||||
# convert from html to rest with pandoc
|
||||
htmlfilenames = [fn for fn in os.listdir(HTML_DIR)
|
||||
if fn.endswith(".html") and not re.sub(r".html", "", fn) in NO_CONVERT]
|
||||
|
||||
for filename in htmlfilenames:
|
||||
|
||||
htmlfilename = os.path.join(HTML_DIR, filename)
|
||||
|
||||
string = "".join(open(htmlfilename, 'r').readlines())
|
||||
string = re.sub(r'<p class="summary">[A-Za-z0-9 ]*</p>', "", string)
|
||||
string = re.sub(r"<wiki:toc max_depth="[0-9]" />", "", string)
|
||||
string = re.sub(r"<p>#settings Featured</p>", "", string)
|
||||
#string = re.sub(r'<wiki:comment>[<>;a-zA\/\n-&Z0-9 ]*</wiki:comment>', "", string)
|
||||
f = open(htmlfilename, 'w')
|
||||
f.write(string)
|
||||
f.close()
|
||||
|
||||
rstfilename = os.path.join(REST_DIR, re.sub(r".html$", ".rst", filename))
|
||||
print "pandoc: converting %s -> %s" % (htmlfilename, rstfilename)
|
||||
subprocess.call([PANDOC_EXE, "--from=html", "--to=rst", "-o", rstfilename, htmlfilename])
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
try:
|
||||
wiki2rest()
|
||||
except Exception, e:
|
||||
print e
|
||||
print "Make sure to read this file's header to make sure everything is correctly set up. "
|
||||
sys.exit()
|
||||
|
||||
import shutil
|
||||
try:
|
||||
shutil.rmtree(SPHINX_WIKI_DIR)
|
||||
print "Deleted old %s." % SPHINX_WIKI_DIR
|
||||
except OSError:
|
||||
pass
|
||||
print "Copying %s -> %s" % (REST_DIR, SPHINX_WIKI_DIR)
|
||||
shutil.copytree(REST_DIR, SPHINX_WIKI_DIR)
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue