mirror of
https://github.com/evennia/evennia.git
synced 2026-03-16 21:06:30 +01:00
Copy doc tools from develop
This commit is contained in:
parent
ca97c9bda0
commit
c52f505d00
127 changed files with 2927 additions and 1427 deletions
|
|
@ -1,5 +1,8 @@
|
|||
# Makefile to control Evennia documentation building.
|
||||
# Most common commands are `make help`, `make quick` and `make local`.
|
||||
SOURCEDIR = source
|
||||
BUILDDIR = build
|
||||
AUTODOCDIR = $(SOURCEDIR)/api
|
||||
|
||||
# You can set these variables from the command line, and also
|
||||
# from the environment for the first two.
|
||||
|
|
@ -7,12 +10,9 @@ SPHINXOPTS ?=
|
|||
SPHINXBUILD ?= sphinx-build
|
||||
SPHINXMULTIVERSION ?= sphinx-multiversion
|
||||
SPHINXAPIDOC ?= sphinx-apidoc
|
||||
SPHINXAPIDOCOPTS = --tocfile evennia-api --module-first --force
|
||||
SPHINXAPIDOCOPTS = --tocfile evennia-api --module-first --force -d 6 --separate --templatedir=$(SOURCEDIR)/_templates/
|
||||
SPHINXAPIDOCENV = members,undoc-members,show-inheritance
|
||||
SPHINXAPIDOCEXCLUDE = */migrations/*
|
||||
SOURCEDIR = source
|
||||
BUILDDIR = build
|
||||
AUTODOCDIR = $(SOURCEDIR)/api
|
||||
SPHINXAPIDOCEXCLUDE = ../*/migrations/* ../evennia/game_template/* ../evennia/*/tests/* ../evennia/*/tests.py
|
||||
|
||||
EVDIR ?= $(realpath ../evennia)
|
||||
EVGAMEDIR ?= $(realpath ../../gamedir)
|
||||
|
|
@ -20,7 +20,8 @@ EVGAMEDIR ?= $(realpath ../../gamedir)
|
|||
cblue = $(shell echo "\033[1m\033[34m")
|
||||
cnorm = $(shell echo "\033[0m")
|
||||
|
||||
QUICKFILES=$(SOURCEDIR)/*.md
|
||||
# set specific files to only run for quick run (even if unset, will still not build new api docs)
|
||||
QUICKFILES=
|
||||
|
||||
|
||||
# Put it first so that "make" without argument is like "make help".
|
||||
|
|
@ -30,9 +31,9 @@ help:
|
|||
@echo " $(cblue)install$(cnorm) to get build requirements"
|
||||
@echo " $(cblue)clean$(cnorm) to remove remnants of a previous build"
|
||||
@echo " $(cblue)local$(cnorm) to build local html docs of the current branch (no multiversion)."
|
||||
@echo " $(cblue)mv-local$(cnorm) to build multiversion html docs, without deploying (req. local git commit)"
|
||||
@echo " $(cblue)deploy$(cnorm) to deploy previously built multiversion docs online (req. commit and github push access)"
|
||||
@echo " $(cblue)release$(cnorm) to build + deploy multiversion docs online (req. commit and github push access)"
|
||||
@echo " $(cblue)mv-local$(cnorm) to build multiversion html docs, without deploying (req: local git commit first)"
|
||||
@echo " $(cblue)deploy$(cnorm) to deploy previously built multiversion docs online (req: commit and github push access)"
|
||||
@echo " $(cblue)release$(cnorm) to build + deploy multiversion docs online (req: commit and github push access)"
|
||||
|
||||
|
||||
.PHONY: help Makefile
|
||||
|
|
@ -55,17 +56,27 @@ _multiversion-check-env:
|
|||
_clean_api_index:
|
||||
rm source/api/*
|
||||
|
||||
# remove supervluous 'module' and 'package' text from api headers
|
||||
_reformat_apidoc_headers:
|
||||
for f in source/api/*.rst; do\
|
||||
perl -pi -e 's/(module|package)$$// if $$. == 1' $$f ;\
|
||||
done
|
||||
|
||||
_autodoc-index:
|
||||
make _clean_api_index
|
||||
@EVDIR=$(EVDIR) EVGAMEDIR=$(EVGAMEDIR) SPHINX_APIDOC_OPTIONS=$(SPHINXAPIDOCENV) $(SPHINXAPIDOC) $(SPHINXAPIDOCOPTS) -o $(SOURCEDIR)/api/ $(EVDIR) $(SPHINXAPIDOCEXCLUDE)
|
||||
make _reformat_apidoc_headers
|
||||
|
||||
_multiversion-autodoc-index:
|
||||
make _clean_api_index
|
||||
@EVDIR=$(EVDIR) EVGAMEDIR=$(EVGAMEDIR) SPHINX_APIDOC_OPTIONS=$(SPHINXAPIDOCENV) $(SPHINXAPIDOC) $(SPHINXAPIDOCOPTS) -o $(SOURCEDIR)/api/ $(EVDIR) $(SPHINXAPIDOCEXCLUDE)
|
||||
make _reformat_apidoc_headers
|
||||
git diff-index --quiet HEAD || git commit -a -m "Updated API autodoc index."
|
||||
|
||||
_build:
|
||||
_html-build:
|
||||
@EVDIR=$(EVDIR) EVGAMEDIR=$(EVGAMEDIR) $(SPHINXBUILD) $(SPHINXOPTS) "$(SOURCEDIR)" "$(BUILDDIR)/html"
|
||||
|
||||
_quick-build:
|
||||
_quick-html-build:
|
||||
@NOAUTODOC=1 EVDIR=$(EVDIR) EVGAMEDIR=$(EVGAMEDIR) $(SPHINXBUILD) $(SPHINXOPTS) "$(SOURCEDIR)" "$(BUILDDIR)/html" $(QUICKFILES)
|
||||
|
||||
_multiversion-build:
|
||||
|
|
@ -73,6 +84,10 @@ _multiversion-build:
|
|||
|
||||
_multiversion-deploy:
|
||||
@bash -e deploy.sh
|
||||
@EVDIR=$(EVDIR) EVGAMEDIR=$(EVGAMEDIR) $(SPHINXMULTIVERSION) $(SPHINXOPTS) "$(SOURCEDIR)" "$(BUILDDIR)/html" $(SPHINXOPTS)
|
||||
|
||||
_latex-build:
|
||||
@NOAUTODOC=1 EVDIR=$(EVDIR) EVGAMEDIR=$(EVGAMEDIR) $(SPHINXBUILD) -M latexpdf "$(SOURCEDIR)" "$(BUILDDIR)/latex" $(QUICKFILES)
|
||||
|
||||
# main targets
|
||||
|
||||
|
|
@ -81,41 +96,47 @@ install:
|
|||
|
||||
clean:
|
||||
@rm -Rf $(BUILDDIR)
|
||||
@git clean -f -d docs/
|
||||
# @git clean -f -d docs/
|
||||
@echo "Cleaned old build dir and leftover files."
|
||||
|
||||
# TODO remove once done with migration
|
||||
copy:
|
||||
@cd pylib && python copy_from_wiki.py && cd ..
|
||||
make quick
|
||||
# not fully working at this time
|
||||
pdf:
|
||||
make _latex-build
|
||||
@echo ""
|
||||
@echo "Documentation built (single version, no autodocs)."
|
||||
@echo "To see result, open evennia/docs/build/latex/evennia.pdf in a PDF reader."
|
||||
|
||||
quick:
|
||||
make _check-env
|
||||
make _quick-build $(FILES)
|
||||
make _quick-html-build $(FILES)
|
||||
@echo ""
|
||||
@echo "Documentation built (no autodocs). \nTo see result, open evennia/docs/build/html/index.html in a browser."
|
||||
@echo "Documentation built (single version, no autodocs)."
|
||||
@echo "To see result, open evennia/docs/build/html/index.html in a browser."
|
||||
|
||||
local:
|
||||
make _check-env
|
||||
make clean
|
||||
make _autodoc-index
|
||||
make _build
|
||||
make _html-build
|
||||
@echo ""
|
||||
@echo "Documentation built. \nTo see result, open evennia/docs/build/html/index.html in a browser."
|
||||
@echo "Documentation built (single version)."
|
||||
@echo "To see result, open evennia/docs/build/html/index.html in a browser."
|
||||
|
||||
mv-local:
|
||||
make _multiversion-check-env
|
||||
make clean
|
||||
make _multiversion-autodoc-index
|
||||
make _multiversion-build
|
||||
@echo "Documentation built. \nTo see result, open evennia/docs/build/html/versions/<version>/index.html in a browser."
|
||||
@echo ""
|
||||
@echo "Documentation built (multiversion + autodocs)."
|
||||
@echo "To see result, open evennia/docs/build/html/<version>/index.html in a browser."
|
||||
|
||||
deploy:
|
||||
make _multiversion-deploy
|
||||
@echo "Documentation deployed."
|
||||
|
||||
# build and prepare the docs for release
|
||||
release:
|
||||
make mv-local
|
||||
make deploy
|
||||
@echo ""
|
||||
@echo "Deployment complete."
|
||||
@echo "Release complete."
|
||||
|
|
|
|||
211
docs/pylib/auto_link_remapper.py
Normal file
211
docs/pylib/auto_link_remapper.py
Normal file
|
|
@ -0,0 +1,211 @@
|
|||
"""
|
||||
Build a TOC-tree; Sphinx requires it and this makes it easy to just
|
||||
add/build/link new files without needing to explicitly add it to a toctree
|
||||
directive somewhere.
|
||||
|
||||
"""
|
||||
|
||||
import re
|
||||
from collections import defaultdict
|
||||
from sphinx.errors import DocumentError
|
||||
from pathlib import Path
|
||||
from os.path import abspath, dirname, join as pathjoin, sep, relpath
|
||||
|
||||
_IGNORE_FILES = []
|
||||
_SOURCEDIR_NAME = "source"
|
||||
_SOURCE_DIR = pathjoin(dirname(dirname(abspath(__file__))), _SOURCEDIR_NAME)
|
||||
_TOC_FILE = pathjoin(_SOURCE_DIR, "toc.md")
|
||||
_NO_REMAP_STARTSWITH = ["http://", "https://", "github:", "api:",
|
||||
"feature-request", "report-bug", "issue", "bug-report"]
|
||||
|
||||
TXT_REMAPS = {
|
||||
}
|
||||
URL_REMAPS = {
|
||||
}
|
||||
|
||||
_USED_REFS = {}
|
||||
|
||||
_CURRFILE = None
|
||||
|
||||
def auto_link_remapper():
|
||||
"""
|
||||
- Auto-Remaps links to fit with the actual document file structure. Requires
|
||||
all doc files to have a unique name.
|
||||
- Creates source/toc.md file
|
||||
|
||||
"""
|
||||
global _CURRFILE
|
||||
|
||||
print(" -- Auto-Remapper starting.")
|
||||
|
||||
def _get_rel_source_ref(path):
|
||||
"""Get the path relative the source/ dir"""
|
||||
pathparts = path.split("/")
|
||||
# we allow a max of 4 levels of nesting in the source dir
|
||||
ind = pathparts[-5:].index(_SOURCEDIR_NAME)
|
||||
# get the part after source/
|
||||
pathparts = pathparts[-5 + 1 + ind:]
|
||||
url = "/".join(pathparts)
|
||||
# get the reference, without .md
|
||||
url = url.rsplit(".", 1)[0]
|
||||
return url
|
||||
|
||||
toc_map = {}
|
||||
docref_map = defaultdict(dict)
|
||||
|
||||
for path in Path(_SOURCE_DIR).rglob("*.md"):
|
||||
# find the source/ part of the path and strip it out
|
||||
|
||||
if path.name in _IGNORE_FILES:
|
||||
# this is the name including .md
|
||||
continue
|
||||
|
||||
sourcepath = path.as_posix()
|
||||
# get name and url relative to source/
|
||||
fname = path.name.rsplit(".", 1)[0]
|
||||
src_url = _get_rel_source_ref(sourcepath)
|
||||
|
||||
# check for duplicate files
|
||||
if fname in toc_map:
|
||||
duplicate_src_url = toc_map[fname]
|
||||
raise DocumentError(
|
||||
f" Tried to add {src_url}.md, but a file {duplicate_src_url}.md already exists.\n"
|
||||
" Evennia's auto-link-corrector does not accept doc-files with the same \n"
|
||||
" name, even in different folders. Rename one.\n")
|
||||
toc_map[fname] = src_url
|
||||
|
||||
# find relative links to all other files
|
||||
for targetpath in Path(_SOURCE_DIR).rglob("*.md"):
|
||||
|
||||
targetname = targetpath.name.rsplit(".", 1)[0]
|
||||
targetpath = targetpath.as_posix()
|
||||
url = relpath(targetpath, dirname(sourcepath))
|
||||
if not "/" in url:
|
||||
# need to be explicit or there will be link ref collisions between
|
||||
# e.g. TickerHandler page and TickerHandle api node
|
||||
url = "./" + url
|
||||
docref_map[sourcepath][targetname] = url.rsplit(".", 1)[0]
|
||||
|
||||
|
||||
# normal reference-links [txt](urls)
|
||||
ref_regex = re.compile(r"\[(?P<txt>[\w -\[\]\`]+?)\]\((?P<url>.+?)\)", re.I + re.S + re.U + re.M)
|
||||
# in document references
|
||||
ref_doc_regex = re.compile(r"\[(?P<txt>[\w -\`]+?)\]:\s+?(?P<url>.+?)(?=$|\n)", re.I + re.S + re.U + re.M)
|
||||
|
||||
def _sub(match):
|
||||
# inline reference links
|
||||
global _USED_REFS
|
||||
grpdict = match.groupdict()
|
||||
txt, url = grpdict['txt'], grpdict['url']
|
||||
|
||||
txt = TXT_REMAPS.get(txt, txt)
|
||||
url = URL_REMAPS.get(url, url)
|
||||
|
||||
if any(url.startswith(noremap) for noremap in _NO_REMAP_STARTSWITH):
|
||||
return f"[{txt}]({url})"
|
||||
|
||||
if "http" in url and "://" in url:
|
||||
urlout = url
|
||||
else:
|
||||
fname, *part = url.rsplit("/", 1)
|
||||
fname = part[0] if part else fname
|
||||
fname = fname.rsplit(".", 1)[0]
|
||||
fname, *anchor = fname.rsplit("#", 1)
|
||||
|
||||
if not _CURRFILE.endswith("toc.md"):
|
||||
_USED_REFS[fname] = url
|
||||
|
||||
if _CURRFILE in docref_map and fname in docref_map[_CURRFILE]:
|
||||
cfilename = _CURRFILE.rsplit("/", 1)[-1]
|
||||
urlout = docref_map[_CURRFILE][fname] + ('#' + anchor[0] if anchor else '')
|
||||
if urlout != url:
|
||||
print(f" {cfilename}: [{txt}]({url}) -> [{txt}]({urlout})")
|
||||
else:
|
||||
urlout = url
|
||||
|
||||
return f"[{txt}]({urlout})"
|
||||
|
||||
def _sub_doc(match):
|
||||
# reference links set at the bottom of the page
|
||||
global _USED_REFS
|
||||
grpdict = match.groupdict()
|
||||
txt, url = grpdict['txt'], grpdict['url']
|
||||
|
||||
txt = TXT_REMAPS.get(txt, txt)
|
||||
url = URL_REMAPS.get(url, url)
|
||||
|
||||
if any(url.startswith(noremap) for noremap in _NO_REMAP_STARTSWITH):
|
||||
return f"[{txt}]: {url}"
|
||||
|
||||
if "http" in url and "://" in url:
|
||||
urlout = url
|
||||
else:
|
||||
fname, *part = url.rsplit("/", 1)
|
||||
fname = part[0] if part else fname
|
||||
fname = fname.rsplit(".", 1)[0]
|
||||
fname, *anchor = fname.rsplit("#", 1)
|
||||
|
||||
if not _CURRFILE.endswith("toc.md"):
|
||||
_USED_REFS[fname] = url
|
||||
|
||||
if _CURRFILE in docref_map and fname in docref_map[_CURRFILE]:
|
||||
cfilename = _CURRFILE.rsplit("/", 1)[-1]
|
||||
urlout = docref_map[_CURRFILE][fname] + ('#' + anchor[0] if anchor else '')
|
||||
if urlout != url:
|
||||
print(f" {cfilename}: [{txt}]: {url} -> [{txt}]: {urlout}")
|
||||
else:
|
||||
urlout = url
|
||||
|
||||
return f"[{txt}]: {urlout}"
|
||||
|
||||
# replace / correct links in all files
|
||||
count = 0
|
||||
for path in sorted(Path(_SOURCE_DIR).rglob("*.md"), key=lambda p: p.name):
|
||||
|
||||
# from pudb import debugger;debugger.Debugger().set_trace()
|
||||
_CURRFILE = path.as_posix()
|
||||
|
||||
with open(path, 'r') as fil:
|
||||
intxt = fil.read()
|
||||
outtxt = ref_regex.sub(_sub, intxt)
|
||||
outtxt = ref_doc_regex.sub(_sub_doc, outtxt)
|
||||
if intxt != outtxt:
|
||||
with open(path, 'w') as fil:
|
||||
fil.write(outtxt)
|
||||
count += 1
|
||||
print(f" -- Auto-relinked links in {path.name}")
|
||||
|
||||
if count > 0:
|
||||
print(f" -- Auto-corrected links in {count} documents.")
|
||||
|
||||
for (fname, src_url) in sorted(toc_map.items(), key=lambda tup: tup[0]):
|
||||
if fname not in _USED_REFS:
|
||||
print(f" ORPHANED DOC: no refs found to {src_url}.md")
|
||||
|
||||
# write tocfile
|
||||
with open(_TOC_FILE, "w") as fil:
|
||||
fil.write("# Toc\n")
|
||||
|
||||
fil.write("- [API root](api/evennia-api.rst)")
|
||||
|
||||
for ref in sorted(toc_map.values()):
|
||||
|
||||
if ref == "toc":
|
||||
continue
|
||||
|
||||
if "Part1/" in ref:
|
||||
continue
|
||||
|
||||
if not "/" in ref:
|
||||
ref = "./" + ref
|
||||
|
||||
linkname = ref.replace("-", " ")
|
||||
fil.write(f"\n- [{linkname}]({ref})")
|
||||
|
||||
# we add a self-reference so the toc itself is also a part of a toctree
|
||||
fil.write("\n\n```toctree::\n :hidden:\n\n toc\n```")
|
||||
|
||||
print(" -- Auto-Remapper finished.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
auto_link_remapper()
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
# A voice operated elevator using events
|
||||
|
||||
|
||||
- Previous tutorial: [Adding dialogues in events](Dialogues-in-events)
|
||||
- Previous tutorial: [Adding dialogues in events](./Dialogues-in-events)
|
||||
|
||||
This tutorial will walk you through the steps to create a voice-operated elevator, using the [in-game Python system](https://github.com/evennia/evennia/blob/master/evennia/contrib/ingame_python/README.md). This tutorial assumes the in-game Python system is installed in your game. If it isn't, you can follow the installation steps given in [the documentation on in-game Python](https://github.com/evennia/evennia/blob/master/evennia/contrib/ingame_python/README.md), and come back on this tutorial once the system is installed. **You do not need to read** the entire documentation, it's a good reference, but not the easiest way to learn about it. Hence these tutorials.
|
||||
|
||||
|
|
@ -71,7 +71,7 @@ This is our elevator room. It looks a bit empty, feel free to add a prettier de
|
|||
|
||||
But what we want now is to be able to say "1", "2" or "3" and have the elevator move in that direction.
|
||||
|
||||
If you have read [the previous tutorial about adding dialogues in events](Dialogues-in-events), you may remember what we need to do. If not, here's a summary: we need to run some code when somebody speaks in the room. So we need to create a callback (the callback will contain our lines of code). We just need to know on which event this should be set. You can enter `call here` to see the possible events in this room.
|
||||
If you have read [the previous tutorial about adding dialogues in events](./Dialogues-in-events), you may remember what we need to do. If not, here's a summary: we need to run some code when somebody speaks in the room. So we need to create a callback (the callback will contain our lines of code). We just need to know on which event this should be set. You can enter `call here` to see the possible events in this room.
|
||||
|
||||
In the table, you should see the "say" event, which is called when somebody says something in the room. So we'll need to add a callback to this event. Don't worry if you're a bit lost, just follow the following steps, the way they connect together will become more obvious.
|
||||
|
||||
|
|
@ -324,4 +324,4 @@ Again, you can force our beggar to move and see the message we have just set. T
|
|||
- **Q:** what if I need several elevators, do I need to copy/paste these callbacks each time?
|
||||
- **A:** not advisable. There are definitely better ways to handle this situation. One of them is to consider adding the code in the source itself. Another possibility is to call chained events with the expected behavior, which makes porting code very easy. This side of chained events will be shown in the next tutorial.
|
||||
|
||||
- Previous tutorial: [Adding dialogues in events](Dialogues-in-events)
|
||||
- Previous tutorial: [Adding dialogues in events](./Dialogues-in-events)
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ This is how to enter an opinion. Use any markdown needed but stay within your se
|
|||
|
||||
### Griatch (Sept 2, 2019)
|
||||
|
||||
I don't agree with removing explicit keywords as suggested by [Johnny on Aug 29 below](API-refactoring#reduce-usage-of-optionalpositional-arguments-aug-29-2019). Overriding such a method can still be done by `get(self, **kwargs)` if so desired, making the kwargs explicit helps IMO readability of the API. If just giving a generic `**kwargs`, one must read the docstring or even the code to see which keywords are valid.
|
||||
I don't agree with removing explicit keywords as suggested by [Johnny on Aug 29 below](./API-refactoring#reduce-usage-of-optionalpositional-arguments-aug-29-2019). Overriding such a method can still be done by `get(self, **kwargs)` if so desired, making the kwargs explicit helps IMO readability of the API. If just giving a generic `**kwargs`, one must read the docstring or even the code to see which keywords are valid.
|
||||
|
||||
On the other hand, I think it makes sense to as a standard offer an extra `**kwargs` at the end of arg-lists for common methods that are expected to be over-ridden. This make the API more flexible by hinting to the dev that they could expand their own over-ridden implementation with their own keyword arguments if so desired.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,27 +1,27 @@
|
|||
# Accounts
|
||||
|
||||
|
||||
All *users* (real people) that starts a game [Session](Sessions) on Evennia are doing so through an
|
||||
All *users* (real people) that starts a game [Session](./Sessions) on Evennia are doing so through an
|
||||
object called *Account*. The Account object has no in-game representation, it represents a unique
|
||||
game account. In order to actually get on the game the Account must *puppet* an [Object](Objects)
|
||||
(normally a [Character](Objects#Character)).
|
||||
game account. In order to actually get on the game the Account must *puppet* an [Object](./Objects)
|
||||
(normally a [Character](./Objects#Character)).
|
||||
|
||||
Exactly how many Sessions can interact with an Account and its Puppets at once is determined by
|
||||
Evennia's [MULTISESSION_MODE](Sessions#Multisession-mode) setting.
|
||||
Evennia's [MULTISESSION_MODE](./Sessions#Multisession-mode) setting.
|
||||
|
||||
Apart from storing login information and other account-specific data, the Account object is what is
|
||||
chatting on [Channels](Communications). It is also a good place to store [Permissions](Locks) to be
|
||||
chatting on [Channels](./Communications). It is also a good place to store [Permissions](./Locks) to be
|
||||
consistent between different in-game characters as well as configuration options. The Account
|
||||
object also has its own [CmdSet](Command-Sets), the `AccountCmdSet`.
|
||||
object also has its own [CmdSet](./Command-Sets), the `AccountCmdSet`.
|
||||
|
||||
Logged into default evennia, you can use the `ooc` command to leave your current
|
||||
[character](Objects) and go into OOC mode. You are quite limited in this mode, basically it works
|
||||
[character](./Objects) 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 attempt to
|
||||
(re)puppet a Character.
|
||||
|
||||
Note that the Account object can have, and often does have, a different set of
|
||||
[Permissions](Locks#Permissions) from the Character they control. Normally you should put your
|
||||
[Permissions](./Locks#Permissions) from the Character they control. Normally you should put your
|
||||
permissions on the Account level - this will overrule permissions set on the Character level. For
|
||||
the permissions of the Character to come into play the default `quell` command can be used. This
|
||||
allows for exploring the game using a different permission set (but you can't escalate your
|
||||
|
|
@ -76,7 +76,7 @@ You should now see the Attributes on yourself.
|
|||
|
||||
## Properties on Accounts
|
||||
|
||||
Beyond those properties assigned to all typeclassed objects (see [Typeclasses](Typeclasses)), the
|
||||
Beyond those properties assigned to all typeclassed objects (see [Typeclasses](./Typeclasses)), the
|
||||
Account also has the following custom properties:
|
||||
|
||||
- `user` - a unique link to a `User` Django object, representing the logged-in user.
|
||||
|
|
@ -90,10 +90,10 @@ Account also has the following custom properties:
|
|||
- `is_superuser` (bool: True/False) - if this account is a superuser.
|
||||
|
||||
Special handlers:
|
||||
- `cmdset` - This holds all the current [Commands](Commands) of this Account. By default these are
|
||||
- `cmdset` - This holds all the current [Commands](./Commands) of this Account. By default these are
|
||||
the commands found in the cmdset defined by `settings.CMDSET_ACCOUNT`.
|
||||
- `nicks` - This stores and handles [Nicks](Nicks), in the same way as nicks it works on Objects.
|
||||
For Accounts, nicks are primarily used to store custom aliases for [Channels](Communications#Channels).
|
||||
- `nicks` - This stores and handles [Nicks](./Nicks), in the same way as nicks it works on Objects.
|
||||
For Accounts, nicks are primarily used to store custom aliases for [Channels](./Communications#Channels).
|
||||
|
||||
Selection of special methods (see `evennia.DefaultAccount` for details):
|
||||
- `get_puppet` - get a currently puppeted object connected to the Account and a given session id, if
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
|
||||
**Before doing this tutorial you will probably want to read the intro in
|
||||
[Basic Web tutorial](Web-Tutorial).** Reading the three first parts of the
|
||||
[Basic Web tutorial](./Web-Tutorial).** Reading the three first parts of the
|
||||
[Django tutorial](https://docs.djangoproject.com/en/1.9/intro/tutorial01/) might help as well.
|
||||
|
||||
This tutorial will provide a step-by-step process to installing a wiki on your website.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Adding Command Tutorial
|
||||
|
||||
This is a quick first-time tutorial expanding on the [Commands](Commands) documentation.
|
||||
This is a quick first-time tutorial expanding on the [Commands](./Commands) documentation.
|
||||
|
||||
Let's assume you have just downloaded Evennia, installed it and created your game folder (let's call
|
||||
it just `mygame` here). Now you want to try to add a new command. This is the fastest way to do it.
|
||||
|
|
@ -12,7 +12,7 @@ it just `mygame` here). Now you want to try to add a new command. This is the fa
|
|||
`CmdEcho` in this example.
|
||||
1. Set the class variable `key` to a good command name, like `echo`.
|
||||
1. Give your class a useful _docstring_. A docstring is the string at the very top of a class or function/method. The docstring at the top of the command class is read by Evennia to become the help entry for the Command (see
|
||||
[Command Auto-help](Help-System#command-auto-help-system)).
|
||||
[Command Auto-help](./Help-System#command-auto-help-system)).
|
||||
1. Define a class method `func(self)` that echoes your input back to you.
|
||||
|
||||
Below is an example how this all could look for the echo command:
|
||||
|
|
@ -43,7 +43,7 @@ Below is an example how this all could look for the echo command:
|
|||
|
||||
## Step 2: Adding the Command to a default Cmdset
|
||||
|
||||
The command is not available to use until it is part of a [Command Set](Command-Sets). In this
|
||||
The command is not available to use until it is part of a [Command Set](./Command-Sets). In this
|
||||
example we will go the easiest route and add it to the default Character commandset that already
|
||||
exists.
|
||||
|
||||
|
|
@ -80,13 +80,13 @@ If you have trouble, make sure to check the log for error messages (probably due
|
|||
your command definition).
|
||||
|
||||
> Note: Typing `echotest` will also work. It will be handled as the command `echo` directly followed by
|
||||
its argument `test` (which will end up in `self.args). To change this behavior, you can add the `arg_regex` property alongside `key`, `help_category` etc. [See the arg_regex documentation](Commands#on-arg_regex) for more info.
|
||||
its argument `test` (which will end up in `self.args). To change this behavior, you can add the `arg_regex` property alongside `key`, `help_category` etc. [See the arg_regex documentation](./Commands#on-arg_regex) for more info.
|
||||
|
||||
If you want to overload existing default commands (such as `look` or `get`), just add your new
|
||||
command with the same key as the old one - it will then replace it. Just remember that you must use
|
||||
`@reload` to see any changes.
|
||||
|
||||
See [Commands](Commands) for many more details and possibilities when defining Commands and using
|
||||
See [Commands](./Commands) for many more details and possibilities when defining Commands and using
|
||||
Cmdsets in various ways.
|
||||
|
||||
|
||||
|
|
@ -124,7 +124,7 @@ only make the new merged cmdset permanent on that *single* object. Often you wan
|
|||
this particular class to have this cmdset.
|
||||
|
||||
To make sure all new created objects get your new merged set, put the `cmdset.add` call in your
|
||||
custom [Typeclasses](Typeclasses)' `at_object_creation` method:
|
||||
custom [Typeclasses](./Typeclasses)' `at_object_creation` method:
|
||||
|
||||
```python
|
||||
# e.g. in mygame/typeclasses/objects.py
|
||||
|
|
|
|||
|
|
@ -13,9 +13,9 @@ When you create a new Evennia game (with for example `evennia --init mygame`) Ev
|
|||
automatically create empty child classes `Object`, `Character`, `Room` and `Exit` respectively. They
|
||||
are found `mygame/typeclasses/objects.py`, `mygame/typeclasses/rooms.py` etc.
|
||||
|
||||
> Technically these are all [Typeclassed](Typeclasses), which can be ignored for now. In
|
||||
> Technically these are all [Typeclassed](./Typeclasses), which can be ignored for now. In
|
||||
> `mygame/typeclasses` are also base typeclasses for out-of-character things, notably
|
||||
> [Channels](Communications), [Accounts](Accounts) and [Scripts](Scripts). We don't cover those in
|
||||
> [Channels](./Communications), [Accounts](./Accounts) and [Scripts](./Scripts). We don't cover those in
|
||||
> this tutorial.
|
||||
|
||||
For your own game you will most likely want to expand on these very simple beginnings. It's normal
|
||||
|
|
@ -62,13 +62,13 @@ up.
|
|||
you will find the traceback. The most common error is that you have some sort of syntax error in
|
||||
your class.
|
||||
|
||||
Note that the [Locks](Locks) and [Attribute](Attributes) which are set in the typeclass could just
|
||||
Note that the [Locks](./Locks) and [Attribute](./Attributes) which are set in the typeclass could just
|
||||
as well have been set using commands in-game, so this is a *very* simple example.
|
||||
|
||||
## Storing data on initialization
|
||||
|
||||
The `at_object_creation` is only called once, when the object is first created. This makes it ideal
|
||||
for database-bound things like [Attributes](Attributes). But sometimes you want to create temporary
|
||||
for database-bound things like [Attributes](./Attributes). But sometimes you want to create temporary
|
||||
properties (things that are not to be stored in the database but still always exist every time the
|
||||
object is created). Such properties can be initialized in the `at_init` method on the object.
|
||||
`at_init` is called every time the object is loaded into memory.
|
||||
|
|
@ -86,7 +86,7 @@ def at_init(self):
|
|||
self.ndb.mylist = []
|
||||
```
|
||||
|
||||
> Note: As mentioned in the [Typeclasses](Typeclasses) documentation, `at_init` replaces the use of
|
||||
> Note: As mentioned in the [Typeclasses](./Typeclasses) documentation, `at_init` replaces the use of
|
||||
> the standard `__init__` method of typeclasses due to how the latter may be called in situations
|
||||
> other than you'd expect. So use `at_init` where you would normally use `__init__`.
|
||||
|
||||
|
|
|
|||
|
|
@ -4,40 +4,40 @@ The following pages are aimed at game administrators -- the higher-ups that poss
|
|||
|
||||
### Installation and Early Life
|
||||
|
||||
- [Choosing (and installing) an SQL Server](Choosing-An-SQL-Server)
|
||||
- [Getting Started - Installing Evennia](Getting-Started)
|
||||
- [Running Evennia in Docker Containers](Running-Evennia-in-Docker)
|
||||
- [Starting, stopping, reloading and resetting Evennia](Start-Stop-Reload)
|
||||
- [Keeping your game up to date](Updating-Your-Game)
|
||||
- [Resetting your database](Updating-Your-Game#resetting-your-database)
|
||||
- [Making your game available online](Online-Setup)
|
||||
- [Hosting options](Online-Setup#hosting-options)
|
||||
- [Securing your server with SSL/Let's Encrypt](Online-Setup#ssl)
|
||||
- [Listing your game](Evennia-Game-Index) at the online [Evennia game index](http://games.evennia.com)
|
||||
- [Choosing (and installing) an SQL Server](./Choosing-An-SQL-Server)
|
||||
- [Getting Started - Installing Evennia](./Getting-Started)
|
||||
- [Running Evennia in Docker Containers](./Running-Evennia-in-Docker)
|
||||
- [Starting, stopping, reloading and resetting Evennia](./Start-Stop-Reload)
|
||||
- [Keeping your game up to date](./Updating-Your-Game)
|
||||
- [Resetting your database](./Updating-Your-Game#resetting-your-database)
|
||||
- [Making your game available online](./Online-Setup)
|
||||
- [Hosting options](./Online-Setup#hosting-options)
|
||||
- [Securing your server with SSL/Let's Encrypt](./Online-Setup#ssl)
|
||||
- [Listing your game](./Evennia-Game-Index) at the online [Evennia game index](http://games.evennia.com)
|
||||
|
||||
### Customizing the server
|
||||
|
||||
- [Changing the Settings](Server-Conf#Settings-file)
|
||||
- [Changing the Settings](./Server-Conf#Settings-file)
|
||||
- [Available Master Settings](https://github.com/evennia/evennia/blob/master/evennia/settings_default.py)
|
||||
- [Change Evennia's language](Internationalization) (internationalization)
|
||||
- [Apache webserver configuration](Apache-Config) (optional)
|
||||
- [Changing text encodings used by the server](Text-Encodings)
|
||||
- [The Connection Screen](Connection-Screen)
|
||||
- [Guest Logins](Guest-Logins)
|
||||
- [How to connect Evennia to IRC channels](IRC)
|
||||
- [How to connect Evennia to RSS feeds](RSS)
|
||||
- [How to connect Evennia to Grapevine](Grapevine)
|
||||
- [How to connect Evennia to Twitter](How-to-connect-Evennia-to-Twitter)
|
||||
- [Change Evennia's language](./Internationalization) (internationalization)
|
||||
- [Apache webserver configuration](./Apache-Config) (optional)
|
||||
- [Changing text encodings used by the server](./Text-Encodings)
|
||||
- [The Connection Screen](./Connection-Screen)
|
||||
- [Guest Logins](./Guest-Logins)
|
||||
- [How to connect Evennia to IRC channels](./IRC)
|
||||
- [How to connect Evennia to RSS feeds](./RSS)
|
||||
- [How to connect Evennia to Grapevine](./Grapevine)
|
||||
- [How to connect Evennia to Twitter](./How-to-connect-Evennia-to-Twitter)
|
||||
|
||||
### Administrating the running game
|
||||
|
||||
- [Supported clients](Client-Support-Grid) (grid of known client issues)
|
||||
- [Changing Permissions](Building-Permissions) of users
|
||||
- [Banning](Banning) and deleting users
|
||||
- [Summary of abuse-handling tools](Banning#summary-of-abuse-handling-tools) in the default cmdset
|
||||
- [Supported clients](./Client-Support-Grid) (grid of known client issues)
|
||||
- [Changing Permissions](./Building-Permissions) of users
|
||||
- [Banning](./Banning) and deleting users
|
||||
- [Summary of abuse-handling tools](./Banning#summary-of-abuse-handling-tools) in the default cmdset
|
||||
|
||||
### Working with Evennia
|
||||
|
||||
- [Setting up your work environment with version control](Version-Control)
|
||||
- [First steps coding with Evennia](First-Steps-Coding)
|
||||
- [Setting up a continuous integration build environment](Continuous-Integration)
|
||||
- [Setting up your work environment with version control](./Version-Control)
|
||||
- [First steps coding with Evennia](./First-Steps-Coding)
|
||||
- [Setting up a continuous integration build environment](./Continuous-Integration)
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ to pick ideas or even get a starting game to build on. These instructions are ba
|
|||
released as of *Aug 12, 2018*.
|
||||
|
||||
If you are not familiar with what Evennia is, you can read
|
||||
[an introduction here](Evennia-Introduction).
|
||||
[an introduction here](./Evennia-Introduction).
|
||||
|
||||
It's not too hard to run Arx from the sources (of course you'll start with an empty database) but
|
||||
since part of Arx has grown organically, it doesn't follow standard Evennia paradigms everywhere.
|
||||
|
|
@ -28,7 +28,7 @@ Instructions](Getting-Started) for your OS. The difference is that you need to `
|
|||
If you are new to Evennia it's *highly* recommended that you run through the
|
||||
instructions in full - including initializing and starting a new empty game and connecting to it.
|
||||
That way you can be sure Evennia works correctly as a base line. If you have trouble, make sure to
|
||||
read the [Troubleshooting instructions](Getting-Started#troubleshooting) for your
|
||||
read the [Troubleshooting instructions](./Getting-Started#troubleshooting) for your
|
||||
operating system. You can also drop into our
|
||||
[forums](https://groups.google.com/forum/#%21forum/evennia), join `#evennia` on `irc.freenode.net`
|
||||
or chat from the linked [Discord Server](https://discord.gg/NecFePw).
|
||||
|
|
@ -58,7 +58,7 @@ Cd to the root of your directory and clone the released source code from github:
|
|||
A new folder `myarx` should appear next to the ones you already had. You could rename this to
|
||||
something else if you want.
|
||||
|
||||
Cd into `myarx`. If you wonder about the structure of the game dir, you can [read more about it here](Directory-Overview).
|
||||
Cd into `myarx`. If you wonder about the structure of the game dir, you can [read more about it here](./Directory-Overview).
|
||||
|
||||
### Clean up settings
|
||||
|
||||
|
|
@ -84,7 +84,7 @@ except ImportError:
|
|||
```
|
||||
|
||||
> Note: Indents and capitalization matter in Python. Make indents 4 spaces (not tabs) for your own
|
||||
> sanity. If you want a starter on Python in Evennia, [you can look here](Python-basic-introduction).
|
||||
> sanity. If you want a starter on Python in Evennia, [you can look here](./Python-basic-introduction).
|
||||
|
||||
This will import Arx' base settings and override them with the Evennia-default telnet port and give
|
||||
the game a name. The slogan changes the sub-text shown under the name of your game in the website
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ line quite pointless for processing any data from the function. Instead one has
|
|||
- `at_err_kwargs` - an optional dictionary that will be fed as keyword arguments to the `at_err`
|
||||
errback.
|
||||
|
||||
An example of making an asynchronous call from inside a [Command](Commands) definition:
|
||||
An example of making an asynchronous call from inside a [Command](./Commands) definition:
|
||||
|
||||
```python
|
||||
from evennia import utils, Command
|
||||
|
|
@ -136,7 +136,7 @@ sleep.
|
|||
```
|
||||
|
||||
This will delay the execution of the callback for 10 seconds. This function is explored much more in
|
||||
the [Command Duration Tutorial](Command-Duration).
|
||||
the [Command Duration Tutorial](./Command-Duration).
|
||||
|
||||
You can also try the following snippet just see how it works:
|
||||
|
||||
|
|
|
|||
|
|
@ -7,20 +7,20 @@ can give correct subsequent commands. If you are writing a combat system, you mi
|
|||
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) game entities ([Accounts](Accounts), [Objects](Objects),
|
||||
[Scripts](Scripts) and [Channels](Communications)) always have *Attributes* associated with them.
|
||||
[Typeclassed](./Typeclasses) game entities ([Accounts](./Accounts), [Objects](./Objects),
|
||||
[Scripts](./Scripts) and [Channels](./Communications)) 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.
|
||||
|
||||
**Attributes are _not_ secure by default and any player may be able to change them unless you [prevent this behavior](Attributes#locking-and-checking-attributes).**
|
||||
**Attributes are _not_ secure by default and any player may be able to change them unless you [prevent this behavior](./Attributes#locking-and-checking-attributes).**
|
||||
|
||||
## The .db and .ndb shortcuts
|
||||
|
||||
To save persistent data on a Typeclassed object you normally use the `db` (DataBase) operator. Let's
|
||||
try to save some data to a *Rose* (an [Object](Objects)):
|
||||
try to save some data to a *Rose* (an [Object](./Objects)):
|
||||
|
||||
```python
|
||||
# saving
|
||||
|
|
@ -85,13 +85,13 @@ The handlers have normal access methods that allow you to manage and retrieve `A
|
|||
returned, but the method takes keywords for returning the Attribute object itself. By supplying an
|
||||
`accessing_object` to the call one can also make sure to check permissions before modifying
|
||||
anything.
|
||||
- `add(...)` - this adds a new Attribute to the object. An optional [lockstring](Locks) can be
|
||||
- `add(...)` - this adds a new Attribute to the object. An optional [lockstring](./Locks) can be
|
||||
supplied here to restrict future access and also the call itself may be checked against locks.
|
||||
- `remove(...)` - Remove the given Attribute. This can optionally be made to check for permission
|
||||
before performing the deletion. - `clear(...)` - removes all Attributes from object.
|
||||
- `all(...)` - returns all Attributes (of the given category) attached to this object.
|
||||
|
||||
See [this section](Attributes#locking-and-checking-attributes) for more about locking down Attribute
|
||||
See [this section](./Attributes#locking-and-checking-attributes) for more about locking down Attribute
|
||||
access and editing. The `Nattribute` offers no concept of access control.
|
||||
|
||||
Some examples:
|
||||
|
|
@ -116,20 +116,20 @@ An Attribute object is stored in the database. It has the following properties:
|
|||
to `attrname`.
|
||||
- `value` - this is the value of the Attribute. This value can be anything which can be pickled -
|
||||
objects, lists, numbers or what have you (see
|
||||
[this section](Attributes#What_types_of_data_can_I_save_in_an_Attribute) for more info). In the example
|
||||
[this section](./Attributes#What_types_of_data_can_I_save_in_an_Attribute) for more info). In the example
|
||||
`obj.db.attrname = value`, the `value` is stored here.
|
||||
- `category` - this is an optional property that is set to None for most Attributes. Setting this
|
||||
allows to use Attributes for different functionality. This is usually not needed unless you want
|
||||
to use Attributes for very different functionality ([Nicks](Nicks) is an example of using Attributes
|
||||
in this way). To modify this property you need to use the [Attribute Handler](Attributes#The_Attribute_Handler).
|
||||
to use Attributes for very different functionality ([Nicks](./Nicks) is an example of using Attributes
|
||||
in this way). To modify this property you need to use the [Attribute Handler](./Attributes#The_Attribute_Handler).
|
||||
- `strvalue` - this is a separate value field that only accepts strings. This severely limits the
|
||||
data possible to store, but allows for easier database lookups. This property is usually not used
|
||||
except when re-using Attributes for some other purpose ([Nicks](Nicks) use it). It is only
|
||||
accessible via the [Attribute Handler](Attributes#The_Attribute_Handler).
|
||||
except when re-using Attributes for some other purpose ([Nicks](./Nicks) use it). It is only
|
||||
accessible via the [Attribute Handler](./Attributes#The_Attribute_Handler).
|
||||
|
||||
There are also two special properties:
|
||||
|
||||
- `attrtype` - this is used internally by Evennia to separate [Nicks](Nicks), from Attributes (Nicks
|
||||
- `attrtype` - this is used internally by Evennia to separate [Nicks](./Nicks), from Attributes (Nicks
|
||||
use Attributes behind the scenes).
|
||||
- `model` - this is a *natural-key* describing the model this Attribute is attached to. This is on
|
||||
the form *appname.modelclass*, like `objects.objectdb`. It is used by the Attribute and
|
||||
|
|
@ -156,7 +156,7 @@ useful in a few situations though.
|
|||
during heavy loads.
|
||||
- A more valid reason for using non-persistent data is if you *want* to lose your state when logging
|
||||
off. Maybe you are storing throw-away data that are re-initialized at server startup. Maybe you
|
||||
are implementing some caching of your own. Or maybe you are testing a buggy [Script](Scripts) that
|
||||
are implementing some caching of your own. Or maybe you are testing a buggy [Script](./Scripts) that
|
||||
does potentially harmful stuff to your character object. With non-persistent storage you can be sure
|
||||
that whatever is messed up, it's nothing a server reboot can't clear up.
|
||||
- NAttributes have no restrictions at all on what they can store (see next section), since they
|
||||
|
|
@ -185,7 +185,7 @@ not a big deal. But if you are accessing the Attribute as part of some big loop
|
|||
amount of reads/writes you should first extract it to a temporary variable, operate on *that* and
|
||||
then save the result back to the Attribute. If you are storing a more complex structure like a
|
||||
`dict` or a `list` you should make sure to "disconnect" it from the database before looping over it,
|
||||
as mentioned in the [Retrieving Mutable Objects](Attributes#retrieving-mutable-objects) section below.
|
||||
as mentioned in the [Retrieving Mutable Objects](./Attributes#retrieving-mutable-objects) section below.
|
||||
|
||||
### Storing single objects
|
||||
|
||||
|
|
@ -233,7 +233,7 @@ entities you can loop over in a for-loop. Attribute-saving supports the followin
|
|||
Since you can use any combination of the above iterables, this is generally not much of a
|
||||
limitation.
|
||||
|
||||
Any entity listed in the [Single object](Attributes#Storing-Single-Objects) section above can be stored in the iterable.
|
||||
Any entity listed in the [Single object](./Attributes#Storing-Single-Objects) section above can be stored in the iterable.
|
||||
|
||||
> As mentioned in the previous section, database entities (aka typeclasses) are not possible to
|
||||
> pickle. So when storing an iterable, Evennia must recursively traverse the iterable *and all its
|
||||
|
|
@ -339,7 +339,7 @@ already disconnected from the database from the onset.
|
|||
Attributes are normally not locked down by default, but you can easily change that for individual
|
||||
Attributes (like those that may be game-sensitive in games with user-level building).
|
||||
|
||||
First you need to set a *lock string* on your Attribute. Lock strings are specified [Locks](Locks). The relevant lock types are
|
||||
First you need to set a *lock string* on your Attribute. Lock strings are specified [Locks](./Locks). The relevant lock types are
|
||||
|
||||
- `attrread` - limits who may read the value of the Attribute
|
||||
- `attredit` - limits who may set/change this Attribute
|
||||
|
|
|
|||
|
|
@ -91,10 +91,10 @@ Below are other useful commands for dealing with annoying players.
|
|||
- **unban 34** -- Remove ban with id #34
|
||||
|
||||
- **cboot mychannel = thomas** -- Boot a subscriber from a channel you control
|
||||
- **clock mychannel = control:perm(Admin);listen:all();send:all()** -- Fine control of access to your channel using [lock definitions](Locks).
|
||||
- **clock mychannel = control:perm(Admin);listen:all();send:all()** -- Fine control of access to your channel using [lock definitions](./Locks).
|
||||
|
||||
Locking a specific command (like `page`) is accomplished like so:
|
||||
1. Examine the source of the command. [The default `page` command class]( https://github.com/evennia/evennia/blob/master/evennia/commands/default/comms.py#L686) has the lock string **"cmd:not pperm(page_banned)"**. This means that unless the player has the 'permission' "page_banned" they can use this command. You can assign any lock string to allow finer customization in your commands. You might look for the value of an [Attribute](Attributes) or [Tag](Tags), your current location etc.
|
||||
1. Examine the source of the command. [The default `page` command class]( https://github.com/evennia/evennia/blob/master/evennia/commands/default/comms.py#L686) has the lock string **"cmd:not pperm(page_banned)"**. This means that unless the player has the 'permission' "page_banned" they can use this command. You can assign any lock string to allow finer customization in your commands. You might look for the value of an [Attribute](./Attributes) or [Tag](./Tags), your current location etc.
|
||||
2. **perm/account thomas = page_banned** -- Give the account the 'permission' which causes (in this case) the lock to fail.
|
||||
|
||||
- **perm/del/account thomas = page_banned** -- Remove the given permission
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# Batch Code Processor
|
||||
|
||||
|
||||
For an introduction and motivation to using batch processors, see [here](Batch-Processors). This page describes the Batch-*code* processor. The Batch-*command* one is covered [here](Batch-Command-Processor).
|
||||
For an introduction and motivation to using batch processors, see [here](./Batch-Processors). This page describes the Batch-*code* processor. The Batch-*command* one is covered [here](./Batch-Command-Processor).
|
||||
|
||||
## Basic Usage
|
||||
|
||||
|
|
@ -89,7 +89,7 @@ The debug mode is intended to be used when you test out a batchscript. Maybe you
|
|||
|
||||
## Interactive mode
|
||||
|
||||
Interactive mode works very similar to the [batch-command processor counterpart](Batch-Command-Processor). 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 `@batchcode` with the `/interactive` flag to enter interactive mode.
|
||||
Interactive mode works very similar to the [batch-command processor counterpart](./Batch-Command-Processor). 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 `@batchcode` with the `/interactive` flag to enter interactive mode.
|
||||
|
||||
> @batchcode/interactive tutorial_examples.batch_code
|
||||
|
||||
|
|
@ -133,7 +133,7 @@ Global variables won't work in code batch files, each block is executed as stand
|
|||
|
||||
The main practical 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 the current block. There are two ways to do this:
|
||||
|
||||
- Perform a database search for the name of the room you created (since you cannot know in advance which dbref it got assigned). The problem is that a name may not be unique (you may have a lot of "A dark forest" rooms). There is an easy way to handle this though - use [Tags](Tags) or *Aliases*. You can assign any number of tags and/or aliases to any object. Make sure that one of those tags or aliases is unique to the room (like "room56") and you will henceforth be able to always uniquely search and find it later.
|
||||
- Perform a database search for the name of the room you created (since you cannot know in advance which dbref it got assigned). The problem is that a name may not be unique (you may have a lot of "A dark forest" rooms). There is an easy way to handle this though - use [Tags](./Tags) or *Aliases*. You can assign any number of tags and/or aliases to any object. Make sure that one of those tags or aliases is unique to the room (like "room56") and you will henceforth be able to always uniquely search and find it later.
|
||||
- Use the `caller` global property as an inter-block storage. For example, you could have a dictionary of room references in an `ndb`:
|
||||
```python
|
||||
#HEADER
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# Batch Command Processor
|
||||
|
||||
|
||||
For an introduction and motivation to using batch processors, see [here](Batch-Processors). This page describes the Batch-*command* processor. The Batch-*code* one is covered [here](Batch-Code-Processor).
|
||||
For an introduction and motivation to using batch processors, see [here](./Batch-Processors). This page describes the Batch-*command* processor. The Batch-*code* one is covered [here](./Batch-Code-Processor).
|
||||
|
||||
## Basic Usage
|
||||
|
||||
|
|
@ -107,7 +107,7 @@ The main issue is that when you run a batch-command script you (*you*, as in you
|
|||
|
||||
This also means there are several pitfalls when designing and adding certain types of objects. Here are some examples:
|
||||
|
||||
- *Rooms that change your [Command Set](Command-Sets)*: 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 ...
|
||||
- *Rooms that change your [Command Set](./Command-Sets)*: 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!
|
||||
|
||||
|
|
@ -115,7 +115,7 @@ The solution to all these is to plan ahead. Make sure that superusers are never
|
|||
|
||||
## 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](Batch-Code-Processor))
|
||||
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](./Batch-Code-Processor))
|
||||
|
||||
- [GNU Emacs](https://www.gnu.org/software/emacs/) users might find it interesting to use emacs' *evennia mode*. This is an Emacs major mode found in `evennia/utils/evennia-mode.el`. It offers correct syntax highlighting and indentation with `<tab>` when editing `.ev` files in Emacs. See the header of that file for installation instructions.
|
||||
- [VIM](http://www.vim.org/) users can use amfl's [vim-evennia](https://github.com/amfl/vim-evennia) mode instead, see its readme for install instructions.
|
||||
|
|
@ -15,8 +15,8 @@ You can of course still build completely online should you want to - this is cer
|
|||
|
||||
There are two batch processors, the Batch-*command* processor and the Batch-*code* processor. The first one is the simpler of the two. It doesn't require any programming knowledge - you basically just list in-game commands in a text file. The code-processor on the other hand is much more powerful but also more complex - it lets you use Evennia's API to code your world in full-fledged Python code.
|
||||
|
||||
- The [Batch Command Processor](Batch-Command-Processor)
|
||||
- The [Batch Code Processor](Batch-Code-Processor)
|
||||
- The [Batch Command Processor](./Batch-Command-Processor)
|
||||
- The [Batch Code Processor](./Batch-Code-Processor)
|
||||
|
||||
If you plan to use international characters in your batchfiles you are wise to read about *file encodings* below.
|
||||
|
||||
|
|
@ -34,6 +34,6 @@ With this little introduction it should be clear that Evennia can't guess but ha
|
|||
|
||||
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](Text-Encodings) and also in the Wikipedia article [here](http://en.wikipedia.org/wiki/Text_encodings).
|
||||
More help with encodings can be found in the entry [Text Encodings](./Text-Encodings) 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.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# Bootstrap Components and Utilities
|
||||
|
||||
Bootstrap provides many utilities and components you can use when customizing Evennia's web presence. We'll go over a few examples here that you might find useful.
|
||||
> Please take a look at either [the basic web tutorial](Add-a-simple-new-web-page) or [the web character view tutorial](Web-Character-View-Tutorial)
|
||||
> Please take a look at either [the basic web tutorial](./Add-a-simple-new-web-page) or [the web character view tutorial](./Web-Character-View-Tutorial)
|
||||
> to get a feel for how to add pages to Evennia's website to test these examples.
|
||||
|
||||
## General Styling
|
||||
|
|
@ -60,4 +60,4 @@ Bootstrap provides classes to easily add responsive margin and padding. Most of
|
|||
```
|
||||
|
||||
### Forms
|
||||
[Forms](https://getbootstrap.com/docs/4.0/components/forms/) are highly customizable with Bootstrap. For a more in-depth look at how to use forms and their styles in your own Evennia site, please read over [the web character gen tutorial.](Web-Character-Generation)
|
||||
[Forms](https://getbootstrap.com/docs/4.0/components/forms/) are highly customizable with Bootstrap. For a more in-depth look at how to use forms and their styles in your own Evennia site, please read over [the web character gen tutorial.](./Web-Character-Generation)
|
||||
|
|
@ -4,23 +4,23 @@ This section contains information useful to world builders.
|
|||
|
||||
### Building basics
|
||||
|
||||
- [Default in-game commands](Default-Command-Help)
|
||||
- [Building Quick-start](Building-Quickstart)
|
||||
- [Giving build permissions to others](Building-Permissions)
|
||||
- [Adding text tags](TextTags)
|
||||
- [Colored text](TextTags#coloured-text)
|
||||
- [Clickable links](TextTags#clickable-links)
|
||||
- [Inline functions](TextTags#inline-functions)
|
||||
- [Customizing the connection screen](Connection-Screen)
|
||||
- [Default in-game commands](./Default-Command-Help)
|
||||
- [Building Quick-start](./Building-Quickstart)
|
||||
- [Giving build permissions to others](./Building-Permissions)
|
||||
- [Adding text tags](./TextTags)
|
||||
- [Colored text](./TextTags#coloured-text)
|
||||
- [Clickable links](./TextTags#clickable-links)
|
||||
- [Inline functions](./TextTags#inline-functions)
|
||||
- [Customizing the connection screen](./Connection-Screen)
|
||||
|
||||
### Advanced building and World building
|
||||
|
||||
- [Overview of batch processors](Batch-Processors)
|
||||
- [Batch-command processor](Batch-Command-Processor)
|
||||
- [Batch-code processor](Batch-Code-Processor)
|
||||
- [Using the Spawner for individualizing objects](Spawner-and-Prototypes)
|
||||
- [Adding Zones](Zones)
|
||||
- [Overview of batch processors](./Batch-Processors)
|
||||
- [Batch-command processor](./Batch-Command-Processor)
|
||||
- [Batch-code processor](./Batch-Code-Processor)
|
||||
- [Using the Spawner for individualizing objects](./Spawner-and-Prototypes)
|
||||
- [Adding Zones](./Zones)
|
||||
|
||||
### The Tutorial world
|
||||
|
||||
- [Introduction and setup](Tutorial-World-Introduction)
|
||||
- [Introduction and setup](./Tutorial-World-Introduction)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# Building Permissions
|
||||
|
||||
|
||||
*OBS: This gives only a brief introduction to the access system. Locks and permissions are fully detailed* [here](Locks).
|
||||
*OBS: This gives only a brief introduction to the access system. Locks and permissions are fully detailed* [here](./Locks).
|
||||
|
||||
## The super user
|
||||
|
||||
|
|
@ -9,7 +9,7 @@ There are strictly speaking two types of users in Evennia, the *super user* and
|
|||
|
||||
## Assigning permissions
|
||||
|
||||
Whereas permissions can be used for anything, those put in `settings.PERMISSION_HIERARCHY` will have a ranking relative each other as well. We refer to these types of permissions as *hierarchical permissions*. When building locks to check these permissions, the `perm()` [lock function](Locks) is used. By default Evennia creates the following hierarchy (spelled exactly like this):
|
||||
Whereas permissions can be used for anything, those put in `settings.PERMISSION_HIERARCHY` will have a ranking relative each other as well. We refer to these types of permissions as *hierarchical permissions*. When building locks to check these permissions, the `perm()` [lock function](./Locks) is used. By default Evennia creates the following hierarchy (spelled exactly like this):
|
||||
|
||||
1. **Developers** basically have the same access as superusers except that they do *not* sidestep the Permission system. Assign only to really trusted server-admin staff since this level gives access both to server reload/shutdown functionality as well as (and this may be more critical) gives access to the all-powerful `@py` command that allows the execution of arbitrary Python code on the command line.
|
||||
1. **Admins** can do everything *except* affecting the server functions themselves. So an Admin 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.
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
# Building Quickstart
|
||||
|
||||
|
||||
The [default command](Default-Command-Help) definitions coming with Evennia
|
||||
follows a style [similar](Using-MUX-as-a-Standard) to that of MUX, so the
|
||||
The [default command](./Default-Command-Help) definitions coming with Evennia
|
||||
follows a style [similar](./Using-MUX-as-a-Standard) to that of MUX, so the
|
||||
commands should be familiar if you used any such code bases before.
|
||||
|
||||
> Throughout the larger documentation you may come across commands prefixed
|
||||
|
|
@ -63,12 +63,12 @@ If you try the `get` command we will pick up the box. So far so good, but if we
|
|||
|
||||
lock box = get:false()
|
||||
|
||||
Locks represent a rather [big topic](Locks), but for now that will do what we want. This will lock the box so noone can lift it. The exception is superusers, they override all locks and will pick it up anyway. Make sure you are quelling your superuser powers and try to get the box now:
|
||||
Locks represent a rather [big topic](./Locks), but for now that will do what we want. This will lock the box so noone can lift it. The exception is superusers, they override all locks and will pick it up anyway. Make sure you are quelling your superuser powers and try to get the box now:
|
||||
|
||||
> get box
|
||||
You can't get that.
|
||||
|
||||
Think thís default error message looks dull? The `get` command looks for an [Attribute](Attributes) named `get_err_msg` for returning a nicer error message (we just happen to know this, you would need to peek into the [code](https://github.com/evennia/evennia/blob/master/evennia/commands/default/general.py#L235) for the `get` command to find out.). You set attributes using the `set` command:
|
||||
Think thís default error message looks dull? The `get` command looks for an [Attribute](./Attributes) named `get_err_msg` for returning a nicer error message (we just happen to know this, you would need to peek into the [code](https://github.com/evennia/evennia/blob/master/evennia/commands/default/general.py#L235) for the `get` command to find out.). You set attributes using the `set` command:
|
||||
|
||||
set box/get_err_msg = It's way too heavy for you to lift.
|
||||
|
||||
|
|
@ -78,11 +78,11 @@ Try to get it now and you should see a nicer error message echoed back to you. T
|
|||
|
||||
Examine will return the value of attributes, including color codes. `examine here/desc` would return the raw description of your current room (including color codes), so that you can copy-and-paste to set its description to something else.
|
||||
|
||||
You create new Commands (or modify existing ones) in Python outside the game. See the [Adding Commands tutorial](Adding-Command-Tutorial) for help with creating your first own Command.
|
||||
You create new Commands (or modify existing ones) in Python outside the game. See the [Adding Commands tutorial](./Adding-Command-Tutorial) for help with creating your first own Command.
|
||||
|
||||
## Get a Personality
|
||||
|
||||
[Scripts](Scripts) are powerful out-of-character objects useful for many "under the hood" things. One of their optional abilities is to do things on a timer. To try out a first script, let's put one on ourselves. There is an example script in `evennia/contrib/tutorial_examples/bodyfunctions.py` that is called `BodyFunctions`. To add this to us we will use the `script` command:
|
||||
[Scripts](./Scripts) are powerful out-of-character objects useful for many "under the hood" things. One of their optional abilities is to do things on a timer. To try out a first script, let's put one on ourselves. There is an example script in `evennia/contrib/tutorial_examples/bodyfunctions.py` that is called `BodyFunctions`. To add this to us we will use the `script` command:
|
||||
|
||||
script self = tutorial_examples.bodyfunctions.BodyFunctions
|
||||
|
||||
|
|
@ -96,11 +96,11 @@ When you are tired of your character's "insights", kill the script with
|
|||
|
||||
script/stop self = tutorial_examples.bodyfunctions.BodyFunctions
|
||||
|
||||
You create your own scripts in Python, outside the game; the path you give to `script` is literally the Python path to your script file. The [Scripts](Scripts) page explains more details.
|
||||
You create your own scripts in Python, outside the game; the path you give to `script` is literally the Python path to your script file. The [Scripts](./Scripts) page explains more details.
|
||||
|
||||
## 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 to `stone` and changed its description noone would be the wiser. However, with the combined use of custom [Typeclasses](Typeclasses), [Scripts](Scripts) and object-based [Commands](Commands), you could expand it and other items to be as unique, complex and interactive as you want.
|
||||
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 to `stone` and changed its description noone would be the wiser. However, with the combined use of custom [Typeclasses](./Typeclasses), [Scripts](./Scripts) and object-based [Commands](./Commands), 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 named simply `Object`. Let's create an object that is a little more interesting. Under `evennia/contrib/tutorial_examples` there is a module `red_button.py`. It contains the enigmatic `RedButton` typeclass.
|
||||
|
||||
|
|
@ -110,7 +110,7 @@ Let's make us one of _those_!
|
|||
|
||||
We import the RedButton python class the same way you would import it in Python except Evennia makes sure to look in`evennia/contrib/` 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 a few of Evennia's features. You will find that the [Typeclass](Typeclasses) and [Commands](Commands) controlling it are inside `evennia/contrib/tutorial_examples/`.
|
||||
The RedButton is an example object intended to show off a few of Evennia's features. You will find that the [Typeclass](./Typeclasses) and [Commands](./Commands) controlling it are inside `evennia/contrib/tutorial_examples/`.
|
||||
|
||||
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.
|
||||
|
||||
|
|
@ -194,4 +194,4 @@ This will take a while (be patient and don't re-run the command). You will see a
|
|||
|
||||
You will end up with a new exit from Limbo named _tutorial_. Apart from being a little solo-adventure in its own right, the tutorial world is a good source for learning Evennia building (and coding).
|
||||
|
||||
Read [the batch file](https://github.com/evennia/evennia/blob/master/evennia/contrib/tutorial_world/build.ev) to see exactly how it's built, step by step. See also more info about the tutorial world [here](Tutorial-World-Introduction).
|
||||
Read [the batch file](https://github.com/evennia/evennia/blob/master/evennia/contrib/tutorial_world/build.ev) to see exactly how it's built, step by step. See also more info about the tutorial world [here](./Tutorial-World-Introduction).
|
||||
|
|
|
|||
|
|
@ -20,9 +20,9 @@ This makes it so that everyone can control the mech. More mechs to the people! (
|
|||
|
||||
Before we continue, let’s make a brief detour. Evennia is very flexible about its objects and even more flexible about using and adding commands to those objects. Here are some ground rules well worth remembering for the remainder of this article:
|
||||
|
||||
- The [Account](Accounts) represents the real person logging in and has no game-world existence.
|
||||
- Any [Object](Objects) can be puppeted by an Account (with proper permissions).
|
||||
- [Characters](Objects#characters), [Rooms](Objects#rooms), and [Exits](Objects#exits) are just children of normal Objects.
|
||||
- The [Account](./Accounts) represents the real person logging in and has no game-world existence.
|
||||
- Any [Object](./Objects) can be puppeted by an Account (with proper permissions).
|
||||
- [Characters](./Objects#characters), [Rooms](./Objects#rooms), and [Exits](./Objects#exits) are just children of normal Objects.
|
||||
- Any Object can be inside another (except if it creates a loop).
|
||||
- Any Object can store custom sets of commands on it. Those commands can:
|
||||
- be made available to the puppeteer (Account),
|
||||
|
|
@ -97,7 +97,7 @@ about the missiles being fired and has different `key` and `aliases`. We leave
|
|||
that up to you to create as an exercise. You could have it print "WOOSH! The
|
||||
mech launches missiles against <target>!", for example.
|
||||
|
||||
Now we shove our commands into a command set. A [Command Set](Command-Sets) (CmdSet) is a container holding any number of commands. The command set is what we will store on the mech.
|
||||
Now we shove our commands into a command set. A [Command Set](./Command-Sets) (CmdSet) is a container holding any number of commands. The command set is what we will store on the mech.
|
||||
|
||||
```python
|
||||
# in the same file mygame/commands/mechcommands.py
|
||||
|
|
@ -138,7 +138,7 @@ There we go, one functioning mech. Try your own `launch` command and see that it
|
|||
|
||||
What we’ve done so far is just to make a normal Object, describe it and put some commands on it. This is great for testing. The way we added it, the MechCmdSet will even go away if we reload the server. Now we want to make the mech an actual object “type” so we can create mechs without those extra steps. For this we need to create a new Typeclass.
|
||||
|
||||
A [Typeclass](Typeclasses) is a near-normal Python class that stores its existence to the database behind the scenes. A Typeclass is created in a normal Python source file:
|
||||
A [Typeclass](./Typeclasses) is a near-normal Python class that stores its existence to the database behind the scenes. A Typeclass is created in a normal Python source file:
|
||||
|
||||
```python
|
||||
# in the new file mygame/typeclasses/mech.py
|
||||
|
|
|
|||
|
|
@ -5,27 +5,27 @@
|
|||
|
||||
## Table of Contents
|
||||
|
||||
- [Removing default commands](Coding-FAQ#removing-default-commands)
|
||||
- [Preventing character from moving based on a condition](Coding-FAQ#preventing-character-from-moving-based-on-a-condition)
|
||||
- [Reference initiating object in an EvMenu command](Coding-FAQ#reference-initiating-object-in-an-evmenu-command)
|
||||
- [Adding color to default Evennia Channels](Coding-FAQ#adding-color-to-default-evennia-channels)
|
||||
- [Selectively turn off commands in a room](Coding-FAQ#selectively-turn-off-commands-in-a-room)
|
||||
- [Select Command based on a condition](Coding-FAQ#select-command-based-on-a-condition)
|
||||
- [Automatically updating code when reloading](Coding-FAQ#automatically-updating-code-when-reloading)
|
||||
- [Changing all exit messages](Coding-FAQ#changing-all-exit-messages)
|
||||
- [Add parsing with the "to" delimiter](Coding-FAQ#add-parsing-with-the-to-delimiter)
|
||||
- [Store last used session IP address](Coding-FAQ#store-last-used-session-ip-address)
|
||||
- [Use wide characters with EvTable](Coding-FAQ#non-latin-characters-in-evtable)
|
||||
- [Removing default commands](./Coding-FAQ#removing-default-commands)
|
||||
- [Preventing character from moving based on a condition](./Coding-FAQ#preventing-character-from-moving-based-on-a-condition)
|
||||
- [Reference initiating object in an EvMenu command](./Coding-FAQ#reference-initiating-object-in-an-evmenu-command)
|
||||
- [Adding color to default Evennia Channels](./Coding-FAQ#adding-color-to-default-evennia-channels)
|
||||
- [Selectively turn off commands in a room](./Coding-FAQ#selectively-turn-off-commands-in-a-room)
|
||||
- [Select Command based on a condition](./Coding-FAQ#select-command-based-on-a-condition)
|
||||
- [Automatically updating code when reloading](./Coding-FAQ#automatically-updating-code-when-reloading)
|
||||
- [Changing all exit messages](./Coding-FAQ#changing-all-exit-messages)
|
||||
- [Add parsing with the "to" delimiter](./Coding-FAQ#add-parsing-with-the-to-delimiter)
|
||||
- [Store last used session IP address](./Coding-FAQ#store-last-used-session-ip-address)
|
||||
- [Use wide characters with EvTable](./Coding-FAQ#non-latin-characters-in-evtable)
|
||||
|
||||
## Removing default commands
|
||||
**Q:** How does one *remove* (not replace) e.g. the default `get` [Command](Commands) from the Character [Command Set](Command-Sets)?
|
||||
**Q:** How does one *remove* (not replace) e.g. the default `get` [Command](./Commands) from the Character [Command Set](./Command-Sets)?
|
||||
|
||||
**A:** Go to `mygame/commands/default_cmdsets.py`. Find the `CharacterCmdSet` class. It has one method named `at_cmdset_creation`. At the end of that method, add the following line: `self.remove(default_cmds.CmdGet())`. See the [Adding Commands Tutorial](Adding-Command-Tutorial) for more info.
|
||||
**A:** Go to `mygame/commands/default_cmdsets.py`. Find the `CharacterCmdSet` class. It has one method named `at_cmdset_creation`. At the end of that method, add the following line: `self.remove(default_cmds.CmdGet())`. See the [Adding Commands Tutorial](./Adding-Command-Tutorial) for more info.
|
||||
|
||||
## Preventing character from moving based on a condition
|
||||
**Q:** How does one keep a character from using any exit, if they meet a certain condition? (I.E. in combat, immobilized, etc.)
|
||||
|
||||
**A:** The `at_before_move` hook is called by Evennia just before performing any move. If it returns `False`, the move is aborted. Let's say we want to check for an [Attribute](Attributes) `cantmove`. Add the following code to the `Character` class:
|
||||
**A:** The `at_before_move` hook is called by Evennia just before performing any move. If it returns `False`, the move is aborted. Let's say we want to check for an [Attribute](./Attributes) `cantmove`. Add the following code to the `Character` class:
|
||||
|
||||
```python
|
||||
def at_before_move(self, destination):
|
||||
|
|
@ -39,7 +39,7 @@ def at_before_move(self, destination):
|
|||
## Reference initiating object in an EvMenu command.
|
||||
**Q:** An object has a Command on it starts up an EvMenu instance. How do I capture a reference to that object for use in the menu?
|
||||
|
||||
**A:** When an [EvMenu](EvMenu) is started, the menu object is stored as `caller.ndb._menutree`. This is a good place to store menu-specific things since it will clean itself up when the menu closes. When initiating the menu, any additional keywords you give will be available for you as properties on this menu object:
|
||||
**A:** When an [EvMenu](./EvMenu) is started, the menu object is stored as `caller.ndb._menutree`. This is a good place to store menu-specific things since it will clean itself up when the menu closes. When initiating the menu, any additional keywords you give will be available for you as properties on this menu object:
|
||||
|
||||
```python
|
||||
class MyObjectCommand(Command):
|
||||
|
|
@ -81,7 +81,7 @@ Additional hint: To make colors easier to change from one place you could instea
|
|||
## Selectively turn off commands in a room
|
||||
**Q:** I want certain commands to turn off in a given room. They should still work normally for staff.
|
||||
|
||||
**A:** This is done using a custom cmdset on a room [locked with the 'call' lock type](Locks). Only if this lock is passed will the commands on the room be made available to an object inside it. Here is an example of a room where certain commands are disabled for non-staff:
|
||||
**A:** This is done using a custom cmdset on a room [locked with the 'call' lock type](./Locks). Only if this lock is passed will the commands on the room be made available to an object inside it. Here is an example of a room where certain commands are disabled for non-staff:
|
||||
|
||||
```python
|
||||
# in mygame/typeclasses/rooms.py
|
||||
|
|
@ -114,7 +114,7 @@ After `@reload`, make some `BlockingRooms` (or switch a room to it with `@typecl
|
|||
## Select Command based on a condition
|
||||
**Q:** I want a command to be available only based on a condition. For example I want the "werewolf" command to only be available on a full moon, from midnight to three in-game time.
|
||||
|
||||
**A:** This is easiest accomplished by putting the "werewolf" command on the Character as normal, but to [lock](Locks) it with the "cmd" type lock. Only if the "cmd" lock type is passed will the command be available.
|
||||
**A:** This is easiest accomplished by putting the "werewolf" command on the Character as normal, but to [lock](./Locks) it with the "cmd" type lock. Only if the "cmd" lock type is passed will the command be available.
|
||||
|
||||
```python
|
||||
# in mygame/commands/command.py
|
||||
|
|
@ -128,7 +128,7 @@ class CmdWerewolf(Command):
|
|||
def func(self):
|
||||
# ...
|
||||
```
|
||||
Add this to the [default cmdset as usual](Adding-Command-Tutorial). The `is_full_moon` [lock function](Locks#lock-functions) does not yet exist. We must create that:
|
||||
Add this to the [default cmdset as usual](./Adding-Command-Tutorial). The `is_full_moon` [lock function](./Locks#lock-functions) does not yet exist. We must create that:
|
||||
|
||||
```python
|
||||
# in mygame/server/conf/lockfuncs.py
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ Here are some pointers to get you going.
|
|||
|
||||
### Python
|
||||
|
||||
Evennia is developed using Python. Even if you are more of a designer than a coder, it is wise to learn how to read and understand basic Python code. If you are new to Python, or need a refresher, take a look at our two-part [Python introduction](Python-basic-introduction).
|
||||
Evennia is developed using Python. Even if you are more of a designer than a coder, it is wise to learn how to read and understand basic Python code. If you are new to Python, or need a refresher, take a look at our two-part [Python introduction](./Python-basic-introduction).
|
||||
|
||||
### Explore Evennia interactively
|
||||
|
||||
|
|
@ -24,9 +24,9 @@ This will open an Evennia-aware python shell (using ipython). From within this s
|
|||
import evennia
|
||||
evennia.<TAB>
|
||||
|
||||
That is, enter `evennia.` and press the `<TAB>` key. This will show you all the resources made available at the top level of Evennia's "flat API". See the [flat API](Evennia-API) page for more info on how to explore it efficiently.
|
||||
That is, enter `evennia.` and press the `<TAB>` key. This will show you all the resources made available at the top level of Evennia's "flat API". See the [flat API](./Evennia-API) page for more info on how to explore it efficiently.
|
||||
|
||||
You can complement your exploration by peeking at the sections of the much more detailed [Developer Central](Developer-Central). The [Tutorials](Tutorials) section also contains a growing collection of system- or implementation-specific help.
|
||||
You can complement your exploration by peeking at the sections of the much more detailed [Developer Central](./Developer-Central). The [Tutorials](./Tutorials) section also contains a growing collection of system- or implementation-specific help.
|
||||
|
||||
### Use a python syntax checker
|
||||
|
||||
|
|
@ -34,13 +34,13 @@ Evennia works by importing your own modules and running them as part of the serv
|
|||
|
||||
### Plan before you code
|
||||
|
||||
Before you start coding away at your dream game, take a look at our [Game Planning](Game-Planning) page. It might hopefully help you avoid some common pitfalls and time sinks.
|
||||
Before you start coding away at your dream game, take a look at our [Game Planning](./Game-Planning) page. It might hopefully help you avoid some common pitfalls and time sinks.
|
||||
|
||||
### Code in your game folder, not in the evennia/ repository
|
||||
|
||||
As part of the Evennia setup you will create a game folder to host your game code. This is your home. You should *never* need to modify anything in the `evennia` library (anything you download from us, really). You import useful functionality from here and if you see code you like, copy&paste it out into your game folder and edit it there.
|
||||
|
||||
If you find that Evennia doesn't support some functionality you need, make a [Feature Request](feature-request) about it. Same goes for [bugs][bug]. If you add features or fix bugs yourself, please consider [Contributing](Contributing) your changes upstream!
|
||||
If you find that Evennia doesn't support some functionality you need, make a [Feature Request](feature-request) about it. Same goes for [bugs][bug]. If you add features or fix bugs yourself, please consider [Contributing](./Contributing) your changes upstream!
|
||||
|
||||
### Learn to read tracebacks
|
||||
|
||||
|
|
|
|||
|
|
@ -148,11 +148,11 @@ deferred = utils.delay(10, _callback, obj, "Echo!", persistent=False)
|
|||
|
||||
```
|
||||
|
||||
This creates an asynchronous delayed call. It will fire the given callback function after the given number of seconds. This is a very light wrapper over a Twisted [Deferred](https://twistedmatrix.com/documents/current/core/howto/defer.html). Normally this is run non-persistently, which means that if the server is `@reload`ed before the delay is over, the callback will never run (the server forgets it). If setting `persistent` to True, the delay will be stored in the database and survive a `@reload` - but for this to work it is susceptible to the same limitations incurred when saving to an [Attribute](Attributes).
|
||||
This creates an asynchronous delayed call. It will fire the given callback function after the given number of seconds. This is a very light wrapper over a Twisted [Deferred](https://twistedmatrix.com/documents/current/core/howto/defer.html). Normally this is run non-persistently, which means that if the server is `@reload`ed before the delay is over, the callback will never run (the server forgets it). If setting `persistent` to True, the delay will be stored in the database and survive a `@reload` - but for this to work it is susceptible to the same limitations incurred when saving to an [Attribute](./Attributes).
|
||||
|
||||
The `deferred` return object can usually be ignored, but calling its `.cancel()` method will abort the delay prematurely.
|
||||
|
||||
`utils.delay` is the lightest form of delayed call in Evennia. For other way to create time-bound tasks, see the [TickerHandler](TickerHandler) and [Scripts](Scripts).
|
||||
`utils.delay` is the lightest form of delayed call in Evennia. For other way to create time-bound tasks, see the [TickerHandler](./TickerHandler) and [Scripts](./Scripts).
|
||||
|
||||
> Note that many delayed effects can be achieved without any need for an active timer. For example if you have a trait that should recover a point every 5 seconds you might just need its value when it's needed, but checking the current time and calculating on the fly what value it should have.
|
||||
|
||||
|
|
@ -161,7 +161,7 @@ The `deferred` return object can usually be ignored, but calling its `.cancel()`
|
|||
|
||||
This useful function takes two arguments - an object to check and a parent. It returns `True` if object inherits from parent *at any distance* (as opposed to Python's in-built `is_instance()` that will only catch immediate dependence). This function also accepts as input any combination of classes, instances or python-paths-to-classes.
|
||||
|
||||
Note that Python code should usually work with [duck typing](http://en.wikipedia.org/wiki/Duck_typing). But in Evennia's case it can sometimes be useful to check if an object inherits from a given [Typeclass](Typeclasses) as a way of identification. Say for example that we have a typeclass *Animal*. This has a subclass *Felines* which in turn has a subclass *HouseCat*. Maybe there are a bunch of other animal types too, like horses and dogs. Using `inherits_from` will allow you to check for all animals in one go:
|
||||
Note that Python code should usually work with [duck typing](http://en.wikipedia.org/wiki/Duck_typing). But in Evennia's case it can sometimes be useful to check if an object inherits from a given [Typeclass](./Typeclasses) as a way of identification. Say for example that we have a typeclass *Animal*. This has a subclass *Felines* which in turn has a subclass *HouseCat*. Maybe there are a bunch of other animal types too, like horses and dogs. Using `inherits_from` will allow you to check for all animals in one go:
|
||||
|
||||
```python
|
||||
from evennia import utils
|
||||
|
|
@ -220,7 +220,7 @@ need to send byte-data over the wire, `to_str` is the only one you'll need.
|
|||
The difference from Python's in-built `str()` and `bytes()` operators are that
|
||||
the Evennia ones makes use of the `ENCODINGS` setting and will try very hard to
|
||||
never raise a traceback but instead echo errors through logging. See
|
||||
[here](Text-Encodings) for more info.
|
||||
[here](./Text-Encodings) for more info.
|
||||
|
||||
### Ansi Coloring Tools
|
||||
- [evennia.ansi](api:evennia.utils.ansi)
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ database, you need to use the caster for the storage.
|
|||
self.caller.db.firestorm_lastcast = now
|
||||
```
|
||||
|
||||
Since we are storing as an [Attribute](Attributes), we need to identify the
|
||||
Since we are storing as an [Attribute](./Attributes), we need to identify the
|
||||
variable as `firestorm_lastcast` so we are sure we get the right one (we'll
|
||||
likely have other skills with cooldowns after all). But this method of
|
||||
using cooldowns also has the advantage of working *between* commands - you can
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
|
||||
Before reading this tutorial, if you haven't done so already, you might want to
|
||||
read [the documentation on commands](Commands) to get a basic understanding of
|
||||
read [the documentation on commands](./Commands) to get a basic understanding of
|
||||
how commands work in Evennia.
|
||||
|
||||
In some types of games a command should not start and finish immediately.
|
||||
|
|
@ -40,7 +40,7 @@ class CmdTest(Command):
|
|||
> Important: The `yield` functionality will *only* work in the `func` method of
|
||||
> Commands. It only works because Evennia has especially
|
||||
> catered for it in Commands. If you want the same functionality elsewhere you
|
||||
> must use the [interactive decorator](Async-Process#The-@interactive-decorator).
|
||||
> must use the [interactive decorator](./Async-Process#The-@interactive-decorator).
|
||||
|
||||
The important line is the `yield 10`. It tells Evennia to "pause" the command
|
||||
and to wait for 10 seconds to execute the rest. If you add this command and
|
||||
|
|
@ -159,7 +159,7 @@ The above version will have the echoes arrive one after another, each separated
|
|||
|
||||
As mentioned, a great thing about the delay introduced by `yield` or `utils.delay()` is that it does not block. It just goes on in the background and you are free to play normally in the interim. In some cases this is not what you want however. Some commands should simply "block" other commands while they are running. If you are in the process of crafting a helmet you shouldn't be able to also start crafting a shield at the same time, or if you just did a huge power-swing with your weapon you should not be able to do it again immediately.
|
||||
|
||||
The simplest way of implementing blocking is to use the technique covered in the [Command Cooldown](Command-Cooldown) tutorial. In that tutorial we implemented cooldowns by having the Command store the current time. Next time the Command was called, we compared the current time to the stored time to determine if enough time had passed for a renewed use. This is a *very* efficient, reliable and passive solution. The drawback is that there is nothing to tell the Player when enough time has passed unless they keep trying.
|
||||
The simplest way of implementing blocking is to use the technique covered in the [Command Cooldown](./Command-Cooldown) tutorial. In that tutorial we implemented cooldowns by having the Command store the current time. Next time the Command was called, we compared the current time to the stored time to determine if enough time had passed for a renewed use. This is a *very* efficient, reliable and passive solution. The drawback is that there is nothing to tell the Player when enough time has passed unless they keep trying.
|
||||
|
||||
Here is an example where we will use `utils.delay` to tell the player when the cooldown has passed:
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ You can combine the sending of normal text with the sending (updating of the pro
|
|||
self.msg("This is a text", prompt="This is a prompt")
|
||||
```
|
||||
|
||||
You can update the prompt on demand, this is normally done using [OOB](OOB)-tracking of the relevant Attributes (like the character's health). You could also make sure that attacking commands update the prompt when they cause a change in health, for example.
|
||||
You can update the prompt on demand, this is normally done using [OOB](./OOB)-tracking of the relevant Attributes (like the character's health). You could also make sure that attacking commands update the prompt when they cause a change in health, for example.
|
||||
|
||||
Here is a simple example of the prompt sent/updated from a command class:
|
||||
|
||||
|
|
|
|||
|
|
@ -1,21 +1,21 @@
|
|||
# Command Sets
|
||||
|
||||
|
||||
Command Sets are intimately linked with [Commands](Commands) and you should be familiar with Commands before reading this page. The two pages were split for ease of reading.
|
||||
Command Sets are intimately linked with [Commands](./Commands) and you should be familiar with Commands before reading this page. The two pages were split for ease of reading.
|
||||
|
||||
A *Command Set* (often referred to as a CmdSet or cmdset) is the basic unit for storing one or more *Commands*. A given Command can go into any number of different command sets. Storing Command classes in a command set is the way to make commands available to use in your game.
|
||||
|
||||
When storing a CmdSet on an object, you will make the commands in that command set available to the object. An example is the default command set stored on new Characters. This command set contains all the useful commands, from `look` and `inventory` to `@dig` and `@reload` ([permissions](Locks#Permissions) then limit which players may use them, but that's a separate topic).
|
||||
When storing a CmdSet on an object, you will make the commands in that command set available to the object. An example is the default command set stored on new Characters. This command set contains all the useful commands, from `look` and `inventory` to `@dig` and `@reload` ([permissions](./Locks#Permissions) then limit which players may use them, but that's a separate topic).
|
||||
|
||||
When an account enters a command, cmdsets from the Account, Character, its location, and elsewhere are pulled together into a *merge stack*. This stack is merged together in a specific order to create a single "merged" cmdset, representing the pool of commands available at that very moment.
|
||||
|
||||
An example would be a `Window` object that has a cmdset with two commands in it: `look through window` and `open window`. The command set would be visible to players in the room with the window, allowing them to use those commands only there. You could imagine all sorts of clever uses of this, like a `Television` object which had multiple commands for looking at it, switching channels and so on. The tutorial world included with Evennia showcases a dark room that replaces certain critical commands with its own versions because the Character cannot see.
|
||||
|
||||
If you want a quick start into defining your first commands and using them with command sets, you can head over to the [Adding Command Tutorial](Adding-Command-Tutorial) which steps through things without the explanations.
|
||||
If you want a quick start into defining your first commands and using them with command sets, you can head over to the [Adding Command Tutorial](./Adding-Command-Tutorial) which steps through things without the explanations.
|
||||
|
||||
## Defining Command Sets
|
||||
|
||||
A CmdSet is, as most things in Evennia, defined as a Python class inheriting from the correct parent (`evennia.CmdSet`, which is a shortcut to `evennia.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](Command-Sets#merge-rules) section).
|
||||
A CmdSet is, as most things in Evennia, defined as a Python class inheriting from the correct parent (`evennia.CmdSet`, which is a shortcut to `evennia.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](./Command-Sets#merge-rules) section).
|
||||
|
||||
```python
|
||||
# file mygame/commands/mycmdset.py
|
||||
|
|
@ -84,24 +84,24 @@ Or you could add the cmdset as the *default* cmdset:
|
|||
|
||||
An object can only have one "default" cmdset (but can also have none). This is meant as a safe fall-back even if all other cmdsets fail or are removed. It is always persistent and will not be affected by `cmdset.delete()`. To remove a default cmdset you must explicitly call `cmdset.remove_default()`.
|
||||
|
||||
Command sets are often added to an object in its `at_object_creation` method. For more examples of adding commands, read the [Step by step tutorial](Adding-Command-Tutorial). Generally you can customize which command sets are added to your objects by using `self.cmdset.add()` or `self.cmdset.add_default()`.
|
||||
Command sets are often added to an object in its `at_object_creation` method. For more examples of adding commands, read the [Step by step tutorial](./Adding-Command-Tutorial). Generally you can customize which command sets are added to your objects by using `self.cmdset.add()` or `self.cmdset.add_default()`.
|
||||
|
||||
> Important: Commands are identified uniquely by key *or* alias (see [Commands](Commands)). If any overlap exists, two commands are considered identical. Adding a Command to a command set that already has an identical command will *replace* the previous command. This is very important. You must take this behavior into account when attempting to overload any default Evennia commands with your own. Otherwise, you may accidentally "hide" your own command in your command set when adding a new one that has a matching alias.
|
||||
> Important: Commands are identified uniquely by key *or* alias (see [Commands](./Commands)). If any overlap exists, two commands are considered identical. Adding a Command to a command set that already has an identical command will *replace* the previous command. This is very important. You must take this behavior into account when attempting to overload any default Evennia commands with your own. Otherwise, you may accidentally "hide" your own command in your command set when adding a new one that has a matching alias.
|
||||
|
||||
### Properties on Command Sets
|
||||
|
||||
There are several extra flags that you can set on CmdSets in order to modify how they work. All are optional and will be set to defaults otherwise. Since many of these relate to *merging* cmdsets, you might want to read the [Adding and Merging Command Sets](Command-Sets#adding-and-merging-command-sets) section for some of these to make sense.
|
||||
There are several extra flags that you can set on CmdSets in order to modify how they work. All are optional and will be set to defaults otherwise. Since many of these relate to *merging* cmdsets, you might want to read the [Adding and Merging Command Sets](./Command-Sets#adding-and-merging-command-sets) section for some of these to make sense.
|
||||
|
||||
- `key` (string) - an identifier for the cmdset. This is optional, but should be unique. It is used for display in lists, but also to identify special merging behaviours using the `key_mergetype` dictionary below.
|
||||
- `mergetype` (string) - allows for one of the following string values: "*Union*", "*Intersect*", "*Replace*", or "*Remove*".
|
||||
- `priority` (int) - This defines the merge order of the merge stack - cmdsets will merge in rising order of priority with the highest priority set merging last. During a merger, the commands from the set with the higher priority will have precedence (just what happens depends on the [merge type](Command-Sets#adding-and-merging-command-sets)). If priority is identical, the order in the merge stack determines preference. The priority value must be greater or equal to `-100`. Most in-game sets should usually have priorities between `0` and `100`. Evennia default sets have priorities as follows (these can be changed if you want a different distribution):
|
||||
- `priority` (int) - This defines the merge order of the merge stack - cmdsets will merge in rising order of priority with the highest priority set merging last. During a merger, the commands from the set with the higher priority will have precedence (just what happens depends on the [merge type](./Command-Sets#adding-and-merging-command-sets)). If priority is identical, the order in the merge stack determines preference. The priority value must be greater or equal to `-100`. Most in-game sets should usually have priorities between `0` and `100`. Evennia default sets have priorities as follows (these can be changed if you want a different distribution):
|
||||
- EmptySet: `-101` (should be lower than all other sets)
|
||||
- SessionCmdSet: `-20`
|
||||
- AccountCmdSet: `-10`
|
||||
- CharacterCmdSet: `0`
|
||||
- ExitCmdSet: ` 101` (generally should always be available)
|
||||
- ChannelCmdSet: `101` (should usually always be available) - since exits never accept arguments, there is no collision between exits named the same as a channel even though the commands "collide".
|
||||
- `key_mergetype` (dict) - a dict of `key:mergetype` pairs. This allows this cmdset to merge differently with certain named cmdsets. If the cmdset to merge with has a `key` matching an entry in `key_mergetype`, it will not be merged according to the setting in `mergetype` but according to the mode in this dict. Please note that this is more complex than it may seem due to the [merge order](Command-Sets#adding-and-merging-command-sets) of command sets. Please review that section before using `key_mergetype`.
|
||||
- `key_mergetype` (dict) - a dict of `key:mergetype` pairs. This allows this cmdset to merge differently with certain named cmdsets. If the cmdset to merge with has a `key` matching an entry in `key_mergetype`, it will not be merged according to the setting in `mergetype` but according to the mode in this dict. Please note that this is more complex than it may seem due to the [merge order](./Command-Sets#adding-and-merging-command-sets) of command sets. Please review that section before using `key_mergetype`.
|
||||
- `duplicates` (bool/None default `None`) - this determines what happens when merging same-priority cmdsets containing same-key commands together. The`dupicate` option will *only* apply when merging the cmdset with this option onto one other cmdset with the same priority. The resulting cmdset will *not* retain this `duplicate` setting.
|
||||
- `None` (default): No duplicates are allowed and the cmdset being merged "onto" the old one will take precedence. The result will be unique commands. *However*, the system will assume this value to be `True` for cmdsets on Objects, to avoid dangerous clashes. This is usually the safe bet.
|
||||
- `False`: Like `None` except the system will not auto-assume any value for cmdsets defined on Objects.
|
||||
|
|
@ -118,20 +118,20 @@ There are several extra flags that you can set on CmdSets in order to modify how
|
|||
|
||||
## Command Sets Searched
|
||||
|
||||
When a user issues a command, it is matched against the [merged](Command-Sets#adding-and-merging-command-sets) command sets available to the player at the moment. Which those are may change at any time (such as when the player walks into the room with the `Window` object described earlier).
|
||||
When a user issues a command, it is matched against the [merged](./Command-Sets#adding-and-merging-command-sets) command sets available to the player at the moment. Which those are may change at any time (such as when the player walks into the room with the `Window` object described earlier).
|
||||
|
||||
The currently valid command sets are collected from the following sources:
|
||||
|
||||
- The cmdsets stored on the currently active [Session](Sessions). Default is the empty `SessionCmdSet` with merge priority `-20`.
|
||||
- The cmdsets defined on the [Account](Accounts). Default is the AccountCmdSet with merge priority `-10`.
|
||||
- The cmdsets stored on the currently active [Session](./Sessions). Default is the empty `SessionCmdSet` with merge priority `-20`.
|
||||
- The cmdsets defined on the [Account](./Accounts). Default is the AccountCmdSet with merge priority `-10`.
|
||||
- All cmdsets on the Character/Object (assuming the Account is currently puppeting such a Character/Object). Merge priority `0`.
|
||||
- The cmdsets of all objects carried by the puppeted Character (checks the `call` lock). Will not be included if `no_objs` option is active in the merge stack.
|
||||
- The cmdsets of the Character's current location (checks the `call` lock). Will not be included if `no_objs` option is active in the merge stack.
|
||||
- The cmdsets of objects in the current location (checks the `call` lock). Will not be included if `no_objs` option is active in the merge stack.
|
||||
- The cmdsets of Exits in the location. Merge priority `+101`. Will not be included if `no_exits` *or* `no_objs` option is active in the merge stack.
|
||||
- The [channel](Communications) cmdset containing commands for posting to all channels the account or character is currently connected to. Merge priority `+101`. Will not be included if `no_channels` option is active in the merge stack.
|
||||
- The [channel](./Communications) cmdset containing commands for posting to all channels the account or character is currently connected to. Merge priority `+101`. Will not be included if `no_channels` option is active in the merge stack.
|
||||
|
||||
Note that an object does not *have* to share its commands with its surroundings. A Character's cmdsets should not be shared for example, or all other Characters would get multi-match errors just by being in the same room. The ability of an object to share its cmdsets is managed by its `call` [lock](Locks). For example, [Character objects](Objects) defaults to `call:false()` so that any cmdsets on them can only be accessed by themselves, not by other objects around them. Another example might be to lock an object with `call:inside()` to only make their commands available to objects inside them, or `cmd:holds()` to make their commands available only if they are held.
|
||||
Note that an object does not *have* to share its commands with its surroundings. A Character's cmdsets should not be shared for example, or all other Characters would get multi-match errors just by being in the same room. The ability of an object to share its cmdsets is managed by its `call` [lock](./Locks). For example, [Character objects](./Objects) defaults to `call:false()` so that any cmdsets on them can only be accessed by themselves, not by other objects around them. Another example might be to lock an object with `call:inside()` to only make their commands available to objects inside them, or `cmd:holds()` to make their commands available only if they are held.
|
||||
|
||||
## Adding and Merging Command Sets
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
# Command System
|
||||
|
||||
- [Commands](Commands)
|
||||
- [Command Sets](Command-Sets)
|
||||
- [Command Auto-help](Help-System#command-auto-help-system)
|
||||
- [Commands](./Commands)
|
||||
- [Command Sets](./Command-Sets)
|
||||
- [Command Auto-help](./Help-System#command-auto-help-system)
|
||||
|
||||
See also:
|
||||
- [Default Command Help](Default-Command-Help)
|
||||
- [Adding Command Tutorial](Adding-Command-Tutorial)
|
||||
- [Default Command Help](./Default-Command-Help)
|
||||
- [Adding Command Tutorial](./Adding-Command-Tutorial)
|
||||
|
|
@ -1,18 +1,18 @@
|
|||
# Commands
|
||||
|
||||
|
||||
Commands are intimately linked to [Command Sets](Command-Sets) and you need to read that page too to be familiar with how the command system works. The two pages were split for easy reading.
|
||||
Commands are intimately linked to [Command Sets](./Command-Sets) and you need to read that page too to be familiar with how the command system works. The two pages were split for easy reading.
|
||||
|
||||
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](Default-Command-Help) 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 `evennia/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.
|
||||
The [default commands](./Default-Command-Help) 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 `evennia/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](Command-Sets) (command sets were split into a separate wiki page for ease of reading).
|
||||
There are two components to having a command running - the *Command* class and the [Command Set](./Command-Sets) (command sets were split into a separate wiki page for ease of reading).
|
||||
|
||||
1. A *Command* is a python class containing all the functioning code for what a command does - for example, a *get* command would contain code for picking up objects.
|
||||
1. A *Command Set* (often referred to as a CmdSet or cmdset) is like a container for one or more Commands. A given Command can go into any number of different command sets. Only by putting 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 *chop down*. Or a "Clock" with a cmdset containing the single command *check time*.
|
||||
|
||||
This page goes into full detail about how to use Commands. To fully use them you must also read the page detailing [Command Sets](Command-Sets). There is also a step-by-step [Adding Command Tutorial](Adding-Command-Tutorial) that will get you started quickly without the extra explanations.
|
||||
This page goes into full detail about how to use Commands. To fully use them you must also read the page detailing [Command Sets](./Command-Sets). There is also a step-by-step [Adding Command Tutorial](./Adding-Command-Tutorial) that will get you started quickly without the extra explanations.
|
||||
|
||||
## Defining Commands
|
||||
|
||||
|
|
@ -53,17 +53,17 @@ You define a new command by assigning a few class-global properties on your inhe
|
|||
|
||||
In Evennia there are three types of objects that may call the command. It is important to be aware of this since this will also assign appropriate `caller`, `session`, `sessid` and `account` properties on the command body at runtime. Most often the calling type is `Session`.
|
||||
|
||||
* A [Session](Sessions). This is by far the most common case when a user is entering a command in their client.
|
||||
* `caller` - this is set to the puppeted [Object](Objects) if such an object exists. If no puppet is found, `caller` is set equal to `account`. Only if an Account is not found either (such as before being logged in) will this be set to the Session object itself.
|
||||
* `session` - a reference to the [Session](Sessions) object itself.
|
||||
* A [Session](./Sessions). This is by far the most common case when a user is entering a command in their client.
|
||||
* `caller` - this is set to the puppeted [Object](./Objects) if such an object exists. If no puppet is found, `caller` is set equal to `account`. Only if an Account is not found either (such as before being logged in) will this be set to the Session object itself.
|
||||
* `session` - a reference to the [Session](./Sessions) object itself.
|
||||
* `sessid` - `sessid.id`, a unique integer identifier of the session.
|
||||
* `account` - the [Account](Accounts) object connected to this Session. None if not logged in.
|
||||
* An [Account](Accounts). This only happens if `account.execute_cmd()` was used. No Session information can be obtained in this case.
|
||||
* `account` - the [Account](./Accounts) object connected to this Session. None if not logged in.
|
||||
* An [Account](./Accounts). This only happens if `account.execute_cmd()` was used. No Session information can be obtained in this case.
|
||||
* `caller` - this is set to the puppeted Object if such an object can be determined (without Session info this can only be determined in `MULTISESSION_MODE=0` or `1`). If no puppet is found, this is equal to `account`.
|
||||
* `session` - `None*`
|
||||
* `sessid` - `None*`
|
||||
* `account` - Set to the Account object.
|
||||
* An [Object](Objects). This only happens if `object.execute_cmd()` was used (for example by an NPC).
|
||||
* An [Object](./Objects). This only happens if `object.execute_cmd()` was used (for example by an NPC).
|
||||
* `caller` - This is set to the calling Object in question.
|
||||
* `session` - `None*`
|
||||
* `sessid` - `None*`
|
||||
|
|
@ -76,13 +76,13 @@ In Evennia there are three types of objects that may call the command. It is im
|
|||
Let's say account *Bob* with a character *BigGuy* enters the command *look at sword*. After the system having successfully identified this as 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 either loads an existing Command instance from cache or creates one. After some more checks it then assigns it the following properties:
|
||||
|
||||
- `caller` - The character BigGuy, in this example. This is a reference to the object executing the command. The value of this depends on what type of object is calling the command; see the previous section.
|
||||
- `session` - the [Session](Sessions) Bob uses to connect to the game and control BigGuy (see also previous section).
|
||||
- `session` - the [Session](./Sessions) Bob uses to connect to the game and control BigGuy (see also previous section).
|
||||
- `sessid` - the unique id of `self.session`, for quick lookup.
|
||||
- `account` - the [Account](Accounts) Bob (see previous section).
|
||||
- `account` - the [Account](./Accounts) Bob (see previous section).
|
||||
- `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 be " *at sword*". Note the space kept - Evennia would correctly interpret `lookat sword` too. This is useful for things like `/switches` that should not use space. In the `MuxCommand` class used for default commands, this space is stripped. Also see the `arg_regex` property if you want to enforce a space to make `lookat sword` give a command-not-found error.
|
||||
- `obj` - the game [Object](Objects) 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 an Account or any interactive object with commands defined on it, like in the example of the "check time" command defined on a "Clock" object.
|
||||
- `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](Help-System#command-auto-help-system) (*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*).
|
||||
- `obj` - the game [Object](./Objects) 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 an Account or any interactive object with commands defined on it, like in the example of the "check time" command defined on a "Clock" object.
|
||||
- `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](./Help-System#command-auto-help-system) (*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*).
|
||||
- `raw_string` - this is the raw input coming from the user, without stripping any surrounding whitespace. The only thing that is stripped is the ending newline marker.
|
||||
|
||||
#### Other useful utility methods:
|
||||
|
|
@ -102,11 +102,11 @@ Beyond the properties Evennia always assigns to the command at run-time (listed
|
|||
|
||||
- `key` (string) - the identifier for the command, like `look`. This should (ideally) be unique. A key can consist of more than one word, like "press button" or "pull left lever". Note that *both* `key` and `aliases` below determine the identity of a command. So two commands are considered if either matches. This is important for merging cmdsets described below.
|
||||
- `aliases` (optional list) - a list of alternate names for the command (`["glance", "see", "l"]`). Same name rules as for `key` applies.
|
||||
- `locks` (string) - a [lock definition](Locks), 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 (if you don't provide a lock string, this will be assigned for you).
|
||||
- `locks` (string) - a [lock definition](./Locks), 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 (if you don't provide a lock string, this will be assigned for you).
|
||||
- `help_category` (optional string) - setting this helps to structure the auto-help into categories. If none is set, this will be set to *General*.
|
||||
- `save_for_next` (optional boolean). This defaults to `False`. If `True`, a copy of this command object (along with any changes you have done to it) will be stored by the system and can be accessed by the next command by retrieving `self.caller.ndb.last_cmd`. The next run command will either clear or replace the storage.
|
||||
- `arg_regex` (optional raw string): Used to force the parser to limit itself and tell it when the command-name ends and arguments begin (such as requiring this to be a space or a /switch). This is done with a regular expression. [See the arg_regex section](Commands#on-arg_regex) for the details.
|
||||
- `auto_help` (optional boolean). Defaults to `True`. This allows for turning off the [auto-help system](Help-System#command-auto-help-system) on a per-command basis. This could be useful if you either want to write your help entries manually or hide the existence of a command from `help`'s generated list.
|
||||
- `arg_regex` (optional raw string): Used to force the parser to limit itself and tell it when the command-name ends and arguments begin (such as requiring this to be a space or a /switch). This is done with a regular expression. [See the arg_regex section](./Commands#on-arg_regex) for the details.
|
||||
- `auto_help` (optional boolean). Defaults to `True`. This allows for turning off the [auto-help system](./Help-System#command-auto-help-system) on a per-command basis. This could be useful if you either want to write your help entries manually or hide the existence of a command from `help`'s generated list.
|
||||
- `is_exit` (bool) - this marks the command as being used for an in-game exit. This is, by default, set by all Exit objects and you should not need to set it manually unless you make your own Exit system. It is used for optimization and allows the cmdhandler to easily disregard this command when the cmdset has its `no_exits` flag set.
|
||||
- `is_channel` (bool)- this marks the command as being used for an in-game channel. This is, by default, set by all Channel objects and you should not need to set it manually unless you make your own Channel system. is used for optimization and allows the cmdhandler to easily disregard this command when its cmdset has its `no_channels` flag set.
|
||||
- `msg_all_sessions` (bool): This affects the behavior of the `Command.msg` method. If unset (default), calling `self.msg(text)` from the Command will always only send text to the Session that actually triggered this Command. If set however, `self.msg(text)` will send to all Sessions relevant to the object this Command sits on. Just which Sessions receives the text depends on the object and the server's `MULTISESSION_MODE`.
|
||||
|
|
@ -118,7 +118,7 @@ You should also implement at least two methods, `parse()` and `func()` (You coul
|
|||
- `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. The return value from this method will be returned from the execution as a Twisted Deferred.
|
||||
- `at_post_cmd()` is called after `func()` to handle eventual cleanup.
|
||||
|
||||
Finally, you should always make an informative [doc string](http://www.python.org/dev/peps/pep-0257/#what-is-a-docstring) (`__doc__`) at the top of your class. This string is dynamically read by the [Help System](Help-System) to create the help entry for this command. You should decide on a way to format your help and stick to that.
|
||||
Finally, you should always make an informative [doc string](http://www.python.org/dev/peps/pep-0257/#what-is-a-docstring) (`__doc__`) at the top of your class. This string is dynamically read by the [Help System](./Help-System) 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 "`smile`" command:
|
||||
|
||||
|
|
@ -175,7 +175,7 @@ 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.
|
||||
|
||||
Before you can actually use the command in your game, you must now store it
|
||||
within a *command set*. See the [Command Sets](Command-Sets) page.
|
||||
within a *command set*. See the [Command Sets](./Command-Sets) page.
|
||||
|
||||
### On arg_regex
|
||||
|
||||
|
|
@ -286,7 +286,7 @@ class CmdConfirm(Command):
|
|||
|
||||
This time, when the user enters the 'confirm' command, she will be asked if she wants to go on. Entering 'yes' or "y" (regardless of case) will give the first reply, otherwise the second reply will show.
|
||||
|
||||
> Note again that the `yield` keyword does not store state. If the game reloads while waiting for the user to answer, the user will have to start over. It is not a good idea to use `yield` for important or complex choices, a persistent [EvMenu](EvMenu) might be more appropriate in this case.
|
||||
> Note again that the `yield` keyword does not store state. If the game reloads while waiting for the user to answer, the user will have to start over. It is not a good idea to use `yield` for important or complex choices, a persistent [EvMenu](./EvMenu) might be more appropriate in this case.
|
||||
|
||||
## System commands
|
||||
|
||||
|
|
@ -302,7 +302,7 @@ Here are the exceptional situations that triggers system commands. You can find
|
|||
- Command not found (`syscmdkeys.CMD_NOMATCH`) - No matching command was found. Default is to display the "Huh?" error message.
|
||||
- Several matching commands where found (`syscmdkeys.CMD_MULTIMATCH`) - Default is to show a list of matches.
|
||||
- User is not allowed to execute the command (`syscmdkeys.CMD_NOPERM`) - Default is to display the "Huh?" error message.
|
||||
- Channel (`syscmdkeys.CMD_CHANNEL`) - This is a [Channel](Communications) 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.
|
||||
- Channel (`syscmdkeys.CMD_CHANNEL`) - This is a [Channel](./Communications) 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.
|
||||
- New session connection (`syscmdkeys.CMD_LOGINSTART`). This command name should be put in the `settings.CMDSET_UNLOGGEDIN`. Whenever a new connection is established, this command is always called on the server (default is to show the login screen).
|
||||
|
||||
Below is an example of redefining what happens when the account doesn't provide 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.
|
||||
|
|
@ -321,7 +321,7 @@ Below is an example of redefining what happens when the account doesn't provide
|
|||
|
||||
*Note: This is an advanced topic.*
|
||||
|
||||
Normally Commands are created as fixed classes and used without modification. There are however situations when the exact key, alias or other properties is not possible (or impractical) to pre-code ([Exits](Commands#Exits) is an example of this).
|
||||
Normally Commands are created as fixed classes and used without modification. There are however situations when the exact key, alias or other properties is not possible (or impractical) to pre-code ([Exits](./Commands#Exits) is an example of this).
|
||||
|
||||
To create a command with a dynamic call signature, first define the command body normally in a class (set your `key`, `aliases` to default values), then use the following call (assuming the command class you created is named `MyCommand`):
|
||||
|
||||
|
|
@ -340,9 +340,9 @@ Normally you would define your class and only overload things like `key` and `al
|
|||
|
||||
*Note: This is an advanced topic.*
|
||||
|
||||
Exits are examples of the use of a [Dynamic Command](Commands#Dynamic_Commands).
|
||||
Exits are examples of the use of a [Dynamic Command](./Commands#Dynamic_Commands).
|
||||
|
||||
The functionality of [Exit](Objects) objects in Evennia is not hard-coded in the engine. Instead Exits are normal [typeclassed](Typeclasses) objects that auto-create a [CmdSet](Commands#CmdSets) on themselves when they load. This cmdset has a single dynamically created Command with the same properties (key, aliases and locks) as the Exit object itself. When entering the name of the exit, this dynamic exit-command is triggered and (after access checks) moves the Character to the exit's destination.
|
||||
The functionality of [Exit](./Objects) objects in Evennia is not hard-coded in the engine. Instead Exits are normal [typeclassed](./Typeclasses) objects that auto-create a [CmdSet](./Commands#CmdSets) on themselves when they load. This cmdset has a single dynamically created Command with the same properties (key, aliases and locks) as the Exit object itself. When entering the name of the exit, this dynamic exit-command is triggered and (after access checks) moves the Character to the exit's destination.
|
||||
Whereas you could customize the Exit object and its command to achieve completely different behaviour, you will usually be fine just using the appropriate `traverse_*` hooks on the Exit object. But if you are interested in really changing how things work under the hood, check out `evennia/objects/objects.py` for how the `Exit` typeclass is set up.
|
||||
|
||||
## Command instances are re-used
|
||||
|
|
@ -415,8 +415,8 @@ Any time the user sends text to Evennia, the server tries to figure out if the t
|
|||
- The caller's own currently active CmdSet.
|
||||
- CmdSets defined on the current account, if caller is a puppeted object.
|
||||
- CmdSets defined on the Session itself.
|
||||
- The active CmdSets of eventual objects in the same location (if any). This includes commands on [Exits](Objects#Exits).
|
||||
- Sets of dynamically created *System commands* representing available [Communications](Communications#Channels).
|
||||
- The active CmdSets of eventual objects in the same location (if any). This includes commands on [Exits](./Objects#Exits).
|
||||
- Sets of dynamically created *System commands* representing available [Communications](./Communications#Channels).
|
||||
7. All CmdSets *of the same priority* are merged together in groups. Grouping avoids order-dependent issues of merging multiple same-prio sets onto lower ones.
|
||||
8. All the grouped CmdSets are *merged* in reverse priority into one combined CmdSet according to each set's merge rules.
|
||||
9. 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.
|
||||
|
|
|
|||
|
|
@ -7,18 +7,18 @@ Comms rely on two main database objects - `Msg` and `Channel`. There is also the
|
|||
|
||||
## 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 [Account](Accounts)) and one or more recipients. The recipients may be either other Accounts, or a *Channel* (see below). You can mix recipients to send the message to both Channels and Accounts if you like.
|
||||
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 [Account](./Accounts)) and one or more recipients. The recipients may be either other Accounts, or a *Channel* (see below). You can mix recipients to send the message to both Channels and Accounts 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. This could be useful for allowing senders/receivers to have 'mailboxes' with the messages they want to keep.
|
||||
|
||||
### Properties defined on `Msg`
|
||||
|
||||
- `senders` - this is a reference to one or many [Account](Accounts) or [Objects](Objects) (normally *Characters*) sending the message. This could also be an *External Connection* such as a message coming in over IRC/IMC2 (see below). There is usually only one sender, but the types can also be mixed in any combination.
|
||||
- `receivers` - a list of target [Accounts](Accounts), [Objects](Objects) (usually *Characters*) or *Channels* to send the message to. The types of receivers can be mixed in any combination.
|
||||
- `senders` - this is a reference to one or many [Account](./Accounts) or [Objects](./Objects) (normally *Characters*) sending the message. This could also be an *External Connection* such as a message coming in over IRC/IMC2 (see below). There is usually only one sender, but the types can also be mixed in any combination.
|
||||
- `receivers` - a list of target [Accounts](./Accounts), [Objects](./Objects) (usually *Characters*) or *Channels* to send the message to. The types of receivers can be mixed in any combination.
|
||||
- `header` - this is a text field for storing a title or header for the message.
|
||||
- `message` - the actual text being sent.
|
||||
- `date_sent` - when message was sent (auto-created).
|
||||
- `locks` - a [lock definition](Locks).
|
||||
- `locks` - a [lock definition](./Locks).
|
||||
- `hide_from` - this can optionally hold a list of objects, accounts or channels to hide this `Msg` from. This relationship is stored in the database primarily for optimization reasons, allowing for quickly post-filter out messages not intended for a given target. There is no in-game methods for setting this, it's intended to be done in code.
|
||||
|
||||
You create new messages in code using `evennia.create_message` (or `evennia.utils.create.create_message.`)
|
||||
|
|
@ -29,11 +29,11 @@ You create new messages in code using `evennia.create_message` (or `evennia.util
|
|||
|
||||
## Channels
|
||||
|
||||
Channels are [Typeclassed](Typeclasses) entities, which mean they can be easily extended and their functionality modified. To change which channel typeclass Evennia uses, change settings.BASE_CHANNEL_TYPECLASS.
|
||||
Channels are [Typeclassed](./Typeclasses) entities, which mean they can be easily extended and their functionality modified. To change which channel typeclass Evennia uses, change settings.BASE_CHANNEL_TYPECLASS.
|
||||
|
||||
Channels act as generic distributors of messages. Think of them as "switch boards" redistributing `Msg` or `TempMsg` objects. Internally they hold a list of "listening" objects and any `Msg` (or `TempMsg`) sent to the channel will be distributed out to all channel listeners. Channels have [Locks](Locks) to limit who may listen and/or send messages through them.
|
||||
Channels act as generic distributors of messages. Think of them as "switch boards" redistributing `Msg` or `TempMsg` objects. Internally they hold a list of "listening" objects and any `Msg` (or `TempMsg`) sent to the channel will be distributed out to all channel listeners. Channels have [Locks](./Locks) to limit who may listen and/or send messages through them.
|
||||
|
||||
The *sending* of text to a channel is handled by a dynamically created [Command](Commands) that always have the same name as the channel. This is created for each channel by the global `ChannelHandler`. The Channel command is added to the Account's cmdset and normal command locks are used to determine which channels are possible to write to. When subscribing to a channel, you can then just write the channel name and the text to send.
|
||||
The *sending* of text to a channel is handled by a dynamically created [Command](./Commands) that always have the same name as the channel. This is created for each channel by the global `ChannelHandler`. The Channel command is added to the Account's cmdset and normal command locks are used to determine which channels are possible to write to. When subscribing to a channel, you can then just write the channel name and the text to send.
|
||||
|
||||
The default ChannelCommand (which can be customized by pointing `settings.CHANNEL_COMMAND_CLASS` to your own command), implements a few convenient features:
|
||||
|
||||
|
|
@ -67,4 +67,4 @@ The argument `msgobj` can be either a string, a previously constructed `Msg` or
|
|||
- `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). Channels normally use the access_types `send, control` and `listen`.
|
||||
- `locks` - A [lock definition](./Locks). Channels normally use the access_types `send, control` and `listen`.
|
||||
|
|
@ -19,7 +19,7 @@ When you first connect to your game you are greeted by Evennia's default connect
|
|||
Effective, but not very exciting. You will most likely want to change this to be more unique for your game. This is simple:
|
||||
|
||||
1. Edit `mygame/server/conf/connection_screens.py`.
|
||||
1. [Reload](Start-Stop-Reload) Evennia.
|
||||
1. [Reload](./Start-Stop-Reload) Evennia.
|
||||
|
||||
Evennia will look into this module and locate all *globally defined strings* in it. These strings
|
||||
are used as the text in your connection screen and are shown to the user at startup. If more than
|
||||
|
|
@ -28,8 +28,8 @@ available.
|
|||
|
||||
### Commands available at the Connection Screen
|
||||
|
||||
You can also customize the [Commands](Commands) available to use while the connection screen is
|
||||
You can also customize the [Commands](./Commands) available to use while the connection screen is
|
||||
shown (`connect`, `create` etc). These commands are a bit special since when the screen is running
|
||||
the account is not yet logged in. A command is made available at the login screen by adding them to
|
||||
`UnloggedinCmdSet` in `mygame/commands/default_cmdset.py`. See [Commands](Commands) and the
|
||||
`UnloggedinCmdSet` in `mygame/commands/default_cmdset.py`. See [Commands](./Commands) and the
|
||||
tutorial section on how to add new commands to a default command set.
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ To prepare a CI environment for your `MU*`, it will be necessary to set up some
|
|||
Among those you will need:
|
||||
* A Continuous Integration Environment.
|
||||
* I recommend [TeamCity](https://www.jetbrains.com/teamcity/) which has an in-depth [Setup Guide](https://confluence.jetbrains.com/display/TCD8/Installing+and+Configuring+the+TeamCity+Server)
|
||||
* [Source Control](Version-Control)
|
||||
* [Source Control](./Version-Control)
|
||||
* This could be Git or SVN or any other available SC.
|
||||
|
||||
## Linux TeamCity Setup
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ We always need more eyes and hands on the code. Even if you don't feel confident
|
|||
and reporting when stuff doesn't make sense helps us a lot.
|
||||
|
||||
The most elegant way to contribute code to Evennia is to use GitHub to create a *fork* of the
|
||||
Evennia repository and make your changes to that. Refer to the [Forking Evennia](Version-Control#forking-evennia) version
|
||||
Evennia repository and make your changes to that. Refer to the [Forking Evennia](./Version-Control#forking-evennia) version
|
||||
control instructions for detailed instructions.
|
||||
|
||||
Once you have a fork set up, you can not only work on your own game in a separate branch, you can
|
||||
|
|
@ -72,8 +72,8 @@ Forked repository as described above.
|
|||
* The code itself should follow Evennia's [Code style guidelines][codestyle].
|
||||
* The code must be well documented as described in our [documentation style guide](https://github.com/evennia/evennia/blob/master/CODING_STYLE.md#doc-strings). Expect that your code will be read and should be possible to understand by others. Include comments as well as a header in all modules. If a single file, the header should include info about how to include the contrib in a game (installation instructions). If stored in a subdirectory, this info should go into a new `README.md` file within that directory.
|
||||
* Within reason, your contribution should be designed as genre-agnostic as possible. Limit the amount of game-style-specific code. Assume your code will be applied to a very different game than you had in mind when creating it.
|
||||
* To make the licensing situation clear we assume all contributions are released with the same [license as Evennia](Licensing). If this is not possible for some reason, talk to us and we'll handle it on a case-by-case basis.
|
||||
* Your contribution must be covered by [unit tests](Unit-Testing). Having unit tests will both help make your code more stable and make sure small changes does not break it without it being noticed, it will also help us test its functionality and merge it quicker. If your contribution is a single module, you can add your unit tests to `evennia/contribs/tests.py`. If your contribution is bigger and in its own sub-directory you could just put the tests in your own `tests.py` file (Evennia will find it automatically).
|
||||
* To make the licensing situation clear we assume all contributions are released with the same [license as Evennia](./Licensing). If this is not possible for some reason, talk to us and we'll handle it on a case-by-case basis.
|
||||
* Your contribution must be covered by [unit tests](./Unit-Testing). Having unit tests will both help make your code more stable and make sure small changes does not break it without it being noticed, it will also help us test its functionality and merge it quicker. If your contribution is a single module, you can add your unit tests to `evennia/contribs/tests.py`. If your contribution is bigger and in its own sub-directory you could just put the tests in your own `tests.py` file (Evennia will find it automatically).
|
||||
* Merging of your code into Evennia is not guaranteed. Be ready to receive feedback and to be asked to make corrections or fix bugs. Furthermore, merging a contrib means the Evennia project takes on the responsibility of maintaining and supporting it. For various reasons this may be deemed to be beyond our manpower. However, if your code were to *not* be accepted for merger for some reason, we will instead add a link to your online repository so people can still find and use your work if they want.
|
||||
|
||||
[ohloh]: http://www.ohloh.net/p/evennia
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ instance.
|
|||
## Coordinates as tags
|
||||
|
||||
The first concept might be the most surprising at first glance: we will create coordinates as
|
||||
[tags](Tags).
|
||||
[tags](./Tags).
|
||||
|
||||
> Why not attributes, wouldn't that be easier?
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@
|
|||
their own custom client protocol.*
|
||||
|
||||
|
||||
A [PortalSession](Sessions#Portal-and-Server-Sessions) is the basic data object representing an external
|
||||
connection to the Evennia [Portal](Portal-And-Server) -- usually a human player running a mud client
|
||||
A [PortalSession](./Sessions#Portal-and-Server-Sessions) is the basic data object representing an external
|
||||
connection to the Evennia [Portal](./Portal-And-Server) -- 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*.
|
||||
|
|
@ -25,7 +25,7 @@ You <->
|
|||
InputFunc
|
||||
```
|
||||
|
||||
(See the [Message Path](Messagepath) for the bigger picture of how data flows through Evennia). The parts that needs to be customized to make your own custom protocol is the `Protocol + PortalSession` (which translates between data coming in/out over the wire to/from Evennia internal representation) as well as the `InputFunc` (which handles incoming data).
|
||||
(See the [Message Path](./Messagepath) for the bigger picture of how data flows through Evennia). The parts that needs to be customized to make your own custom protocol is the `Protocol + PortalSession` (which translates between data coming in/out over the wire to/from Evennia internal representation) as well as the `InputFunc` (which handles incoming data).
|
||||
|
||||
## Adding custom Protocols
|
||||
|
||||
|
|
@ -206,7 +206,7 @@ The message will pass through the system such that the sessionhandler will dig o
|
|||
|
||||
### Receiving data
|
||||
|
||||
Just because the protocol is there, does not mean Evennia knows what to do with it. An [Inputfunc](Inputfuncs) must exist to receive it. In the case of the `text` input exemplified above, Evennia alredy handles this input - it will parse it as a Command name followed by its inputs. So handle that you need to simply add a cmdset with commands on your receiving Session (and/or the Object/Character it is puppeting). If not you may need to add your own Inputfunc (see the [Inputfunc](Inputfuncs) page for how to do this.
|
||||
Just because the protocol is there, does not mean Evennia knows what to do with it. An [Inputfunc](./Inputfuncs) must exist to receive it. In the case of the `text` input exemplified above, Evennia alredy handles this input - it will parse it as a Command name followed by its inputs. So handle that you need to simply add a cmdset with commands on your receiving Session (and/or the Object/Character it is puppeting). If not you may need to add your own Inputfunc (see the [Inputfunc](./Inputfuncs) page for how to do this.
|
||||
|
||||
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 *Portal Session*, which is the actual common
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ Okay, let's review this code, but if you're used to Evennia commands, it shouldn
|
|||
1. We import `search_channel`. This is a little helper function that we will use to search for channels by name and aliases, found in `evennia.utils.search`. It's just more convenient.
|
||||
2. Our class `CmdConnect` contains the body of our command to join a channel.
|
||||
3. Notice the key of this command is simply `"+"`. When you enter `+something` in the game, it will try to find a command key `+something`. Failing that, it will look at other potential matches. Evennia is smart enough to understand that when we type `+something`, `+` is the command key and `something` is the command argument. This will, of course, fail if you have a command beginning by `+` conflicting with the `CmdConnect` key.
|
||||
4. We have altered some class attributes, like `auto_help`. If you want to know what they do and why they have changed here, you can check the [documentation on commands](Commands).
|
||||
4. We have altered some class attributes, like `auto_help`. If you want to know what they do and why they have changed here, you can check the [documentation on commands](./Commands).
|
||||
5. In the command body, we begin by extracting the channel name. Remember that this name should be in the command arguments (that is, in `self.args`). Following the same example, if a player enters `+something`, `self.args` should contain `"something"`. We use `search_channel` to see if this channel exists.
|
||||
6. We then check the access level of the channel, to see if the caller can listen to it (not necessarily use it to speak, mind you, just listen to others speak, as these are two different locks on Evennia).
|
||||
7. Finally, we connect the caller if he's not already connected to the channel. We use the channel's `connect` method to do this. Pretty straightforward eh?
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,7 +1,7 @@
|
|||
# Default Exit Errors
|
||||
|
||||
|
||||
Evennia allows for exits to have any name. The command "kitchen" is a valid exit name as well as "jump out the window" or "north". An exit actually consists of two parts: an [Exit Object](Objects) and an [Exit Command](Commands) stored on said exit object. The command has the same key and aliases as the object, which is why you can see the exit in the room and just write its name to traverse it.
|
||||
Evennia allows for exits to have any name. The command "kitchen" is a valid exit name as well as "jump out the window" or "north". An exit actually consists of two parts: an [Exit Object](./Objects) and an [Exit Command](./Commands) stored on said exit object. The command has the same key and aliases as the object, which is why you can see the exit in the room and just write its name to traverse it.
|
||||
|
||||
If you try to enter the name of a non-existing exit, it is thus the same as trying a non-exising command; Evennia doesn't care about the difference:
|
||||
|
||||
|
|
@ -17,7 +17,7 @@ Since we for our particular game *know* that west is an exit direction, it would
|
|||
|
||||
## Adding default error commands
|
||||
|
||||
To solve this you need to be aware of how to [write and add new commands](Adding-Command-Tutorial). What you need to do is to create new commands for all directions you want to support in your game. In this example all we'll do is echo an error message, but you could certainly consider more advanced uses. You add these commands to the default command set. Here is an example of such a set of commands:
|
||||
To solve this you need to be aware of how to [write and add new commands](./Adding-Command-Tutorial). What you need to do is to create new commands for all directions you want to support in your game. In this example all we'll do is echo an error message, but you could certainly consider more advanced uses. You add these commands to the default command set. Here is an example of such a set of commands:
|
||||
|
||||
```python
|
||||
# for example in a file mygame/commands/movecommands.py
|
||||
|
|
@ -73,7 +73,7 @@ After a `@reload` these commands (assuming you don't get any errors - check your
|
|||
> east
|
||||
You cannot move east.
|
||||
|
||||
Further expansions by the exit system (including manipulating the way the Exit command itself is created) can be done by modifying the [Exit typeclass](Typeclasses) directly.
|
||||
Further expansions by the exit system (including manipulating the way the Exit command itself is created) can be done by modifying the [Exit typeclass](./Typeclasses) directly.
|
||||
|
||||
## Additional Comments
|
||||
|
||||
|
|
@ -91,6 +91,6 @@ So why didn't we create a single error command above? Something like this:
|
|||
```
|
||||
The anwer is that this would *not* work and understanding why is important in order to not be confused when working with commands and command sets.
|
||||
|
||||
The reason it doesn't work is because Evennia's [command system](Commands) compares commands *both* by `key` and by `aliases`. If *either* of those match, the two commands are considered *identical* as far as cmdset merging system is concerned.
|
||||
The reason it doesn't work is because Evennia's [command system](./Commands) compares commands *both* by `key` and by `aliases`. If *either* of those match, the two commands are considered *identical* as far as cmdset merging system is concerned.
|
||||
|
||||
So the above example would work fine as long as there were no Exits at all in the room. But what happens when we enter a room with an exit "north"? The Exit's cmdset is merged onto the default one, and since there is an alias match, the system determines our `CmdExitError` to be identical. It is thus overloaded by the Exit command (which also correctly defaults to a higher priority). The result is that you can go through the north exit normally but none of the error messages for the other directions are available since the single error command was completely overloaded by the single matching "north" exit-command.
|
||||
|
|
|
|||
|
|
@ -5,96 +5,96 @@ This page serves as a central nexus for information on using Evennia as well as
|
|||
|
||||
### General Evennia development information
|
||||
|
||||
- [Introduction to coding with Evennia](Coding-Introduction)
|
||||
- [Evennia Licensing FAQ](Licensing)
|
||||
- [Contributing to Evennia](Contributing)
|
||||
- [Introduction to coding with Evennia](./Coding-Introduction)
|
||||
- [Evennia Licensing FAQ](./Licensing)
|
||||
- [Contributing to Evennia](./Contributing)
|
||||
- [Code Style Guide](https://github.com/evennia/evennia/blob/master/CODING_STYLE.md) (Important!)
|
||||
- [Policy for 'MUX-like' default commands](Using-MUX-as-a-Standard)
|
||||
- [Setting up a Git environment for coding](Version-Control)
|
||||
- [Getting started with Travis and Github for continuous integration testing](Using-Travis)
|
||||
- [Planning your own Evennia game](Game-Planning)
|
||||
- [First steps coding Evennia](First-Steps-Coding)
|
||||
- [Translating Evennia](Internationalization#translating-evennia)
|
||||
- [Evennia Quirks](Quirks) to keep in mind.
|
||||
- [Directions for configuring PyCharm with Evennia on Windows](Setting-up-PyCharm)
|
||||
- [Policy for 'MUX-like' default commands](./Using-MUX-as-a-Standard)
|
||||
- [Setting up a Git environment for coding](./Version-Control)
|
||||
- [Getting started with Travis and Github for continuous integration testing](./Using-Travis)
|
||||
- [Planning your own Evennia game](./Game-Planning)
|
||||
- [First steps coding Evennia](./First-Steps-Coding)
|
||||
- [Translating Evennia](./Internationalization#translating-evennia)
|
||||
- [Evennia Quirks](./Quirks) to keep in mind.
|
||||
- [Directions for configuring PyCharm with Evennia on Windows](./Setting-up-PyCharm)
|
||||
|
||||
### Evennia API
|
||||
|
||||
- [Directory Overview](Directory-Overview)
|
||||
- [evennia - the flat API](Evennia-API)
|
||||
- [Running and Testing Python code](Execute-Python-Code)
|
||||
- [Directory Overview](./Directory-Overview)
|
||||
- [evennia - the flat API](./Evennia-API)
|
||||
- [Running and Testing Python code](./Execute-Python-Code)
|
||||
|
||||
#### Core components and protocols
|
||||
|
||||
- [Server and Portal](Portal-And-Server)
|
||||
- [Sessions](Sessions)
|
||||
- [Configuration and module plugins](Server-Conf)
|
||||
- [The message path](Messagepath)
|
||||
- [OOB](OOB) - Out-of-band communication
|
||||
- [Inputfuncs](Inputfuncs)
|
||||
- [Adding new protocols (client APIs) and services](Custom-Protocols)
|
||||
- [Adding new database models](New-Models)
|
||||
- [Running and writing unit tests](Unit-Testing)
|
||||
- [Running profiling](Profiling)
|
||||
- [Debugging your code](Debugging)
|
||||
- [Server and Portal](./Portal-And-Server)
|
||||
- [Sessions](./Sessions)
|
||||
- [Configuration and module plugins](./Server-Conf)
|
||||
- [The message path](./Messagepath)
|
||||
- [OOB](./OOB) - Out-of-band communication
|
||||
- [Inputfuncs](./Inputfuncs)
|
||||
- [Adding new protocols (client APIs) and services](./Custom-Protocols)
|
||||
- [Adding new database models](./New-Models)
|
||||
- [Running and writing unit tests](./Unit-Testing)
|
||||
- [Running profiling](./Profiling)
|
||||
- [Debugging your code](./Debugging)
|
||||
|
||||
#### In-game Commands
|
||||
|
||||
- [Command System overview](Command-System)
|
||||
- [Commands](Commands)
|
||||
- [Command Sets](Command-Sets)
|
||||
- [Command Auto-help](Help-System#command-auto-help-system)
|
||||
- [Command System overview](./Command-System)
|
||||
- [Commands](./Commands)
|
||||
- [Command Sets](./Command-Sets)
|
||||
- [Command Auto-help](./Help-System#command-auto-help-system)
|
||||
|
||||
#### Typeclasses and related concepts
|
||||
|
||||
- [General about Typeclasses](Typeclasses)
|
||||
- [Objects](Objects)
|
||||
- [Characters](Objects#characters)
|
||||
- [Rooms](Objects#rooms)
|
||||
- [Exits](Objects#exits)
|
||||
- [Accounts](Accounts)
|
||||
- [Communications](Communications)
|
||||
- [Channels](Communications#channels)
|
||||
- [Scripts](Scripts)
|
||||
- [Global Scripts](Scripts#Global-Scripts)
|
||||
- [TickerHandler](TickerHandler)
|
||||
- [utils.delay](Coding-Utils#utilsdelay)
|
||||
- [MonitorHandler](MonitorHandler)
|
||||
- [Attributes](Attributes)
|
||||
- [Nicks](Nicks)
|
||||
- [Tags](Tags)
|
||||
- [Tags for Aliases and Permissions](Tags#using-aliases-and-permissions)
|
||||
- [General about Typeclasses](./Typeclasses)
|
||||
- [Objects](./Objects)
|
||||
- [Characters](./Objects#characters)
|
||||
- [Rooms](./Objects#rooms)
|
||||
- [Exits](./Objects#exits)
|
||||
- [Accounts](./Accounts)
|
||||
- [Communications](./Communications)
|
||||
- [Channels](./Communications#channels)
|
||||
- [Scripts](./Scripts)
|
||||
- [Global Scripts](./Scripts#Global-Scripts)
|
||||
- [TickerHandler](./TickerHandler)
|
||||
- [utils.delay](./Coding-Utils#utilsdelay)
|
||||
- [MonitorHandler](./MonitorHandler)
|
||||
- [Attributes](./Attributes)
|
||||
- [Nicks](./Nicks)
|
||||
- [Tags](./Tags)
|
||||
- [Tags for Aliases and Permissions](./Tags#using-aliases-and-permissions)
|
||||
|
||||
#### Web
|
||||
|
||||
- [Web features overview](Web-Features)
|
||||
- [The Webclient](Webclient)
|
||||
- [Web tutorials](Web-Tutorial)
|
||||
- [Web features overview](./Web-Features)
|
||||
- [The Webclient](./Webclient)
|
||||
- [Web tutorials](./Web-Tutorial)
|
||||
|
||||
#### Other systems
|
||||
|
||||
- [Locks](Locks)
|
||||
- [Permissions](Locks#permissions)
|
||||
- [Help System](Help-System)
|
||||
- [Signals](Signals)
|
||||
- [General coding utilities](Coding-Utils)
|
||||
- [Locks](./Locks)
|
||||
- [Permissions](./Locks#permissions)
|
||||
- [Help System](./Help-System)
|
||||
- [Signals](./Signals)
|
||||
- [General coding utilities](./Coding-Utils)
|
||||
- [Utils in evennia.utils.utils](api:evennia.utils.utils)
|
||||
- [Game time](Coding-Utils#game-time)
|
||||
- [Game Menus](EvMenu) (EvMenu)
|
||||
- [Text paging/scrolling](EvMore) (EvMore)
|
||||
- [Text Line Editor](EvEditor) (EvEditor)
|
||||
- [Game time](./Coding-Utils#game-time)
|
||||
- [Game Menus](./EvMenu) (EvMenu)
|
||||
- [Text paging/scrolling](./EvMore) (EvMore)
|
||||
- [Text Line Editor](./EvEditor) (EvEditor)
|
||||
- [Text Tables](github:evennia.utils.evtable) (EvTable)
|
||||
- [Text Form generation](github:evennia.utils.evform) (EvForm)
|
||||
- [Spawner and Prototypes](Spawner-and-Prototypes)
|
||||
- [Inlinefuncs](TextTags#inline-functions)
|
||||
- [Asynchronous execution](Async-Process)
|
||||
- [Spawner and Prototypes](./Spawner-and-Prototypes)
|
||||
- [Inlinefuncs](./TextTags#inline-functions)
|
||||
- [Asynchronous execution](./Async-Process)
|
||||
|
||||
### Developer brainstorms and whitepages
|
||||
|
||||
- [API refactoring](API-refactoring), discussing what parts of the Evennia API needs a refactoring/cleanup/simplification
|
||||
- [Docs refactoring](Docs-refactoring), discussing how to reorganize and structure this wiki/docs better going forward
|
||||
- [Webclient brainstorm](Webclient-brainstorm), some ideas for a future webclient gui
|
||||
- [Roadmap](Roadmap), a tentative list of future major features
|
||||
- [API refactoring](./API-refactoring), discussing what parts of the Evennia API needs a refactoring/cleanup/simplification
|
||||
- [Docs refactoring](./Docs-refactoring), discussing how to reorganize and structure this wiki/docs better going forward
|
||||
- [Webclient brainstorm](./Webclient-brainstorm), some ideas for a future webclient gui
|
||||
- [Roadmap](./Roadmap), a tentative list of future major features
|
||||
- [Change log](https://github.com/evennia/evennia/blob/master/CHANGELOG.md) of big Evennia updates over time
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# Dialogues in events
|
||||
|
||||
|
||||
- Next tutorial: [adding a voice-operated elevator with events](A-voice-operated-elevator-using-events).
|
||||
- Next tutorial: [adding a voice-operated elevator with events](./A-voice-operated-elevator-using-events).
|
||||
|
||||
This tutorial will walk you through the steps to create several dialogues with characters, using the [in-game Python system](https://github.com/evennia/evennia/blob/master/evennia/contrib/ingame_python/README.md). This tutorial assumes the in-game Python system is installed in your game. If it isn't, you can follow the installation steps given in [the documentation on in-game Python](https://github.com/evennia/evennia/blob/master/evennia/contrib/ingame_python/README.md), and come back on this tutorial once the system is installed. **You do not need to read** the entire documentation, it's a good reference, but not the easiest way to learn about it. Hence these tutorials.
|
||||
|
||||
|
|
@ -176,4 +176,4 @@ Notice here that the first lines of dialogue are spoken to the entire room, but
|
|||
- **Q:** is it possible to deploy callbacks on all characters sharing the same prototype?
|
||||
- **A:** not out of the box. This depends on individual settings in code. One can imagine that all characters of some type would share some events, but this is game-specific. Rooms of the same zone could share the same events as well. It is possible to do but requires modification of the source code.
|
||||
|
||||
- Next tutorial: [adding a voice-operated elevator with events](A-voice-operated-elevator-using-events).
|
||||
- Next tutorial: [adding a voice-operated elevator with events](./A-voice-operated-elevator-using-events).
|
||||
|
|
|
|||
|
|
@ -8,41 +8,41 @@ This is an overview of the directories relevant to Evennia coding.
|
|||
The game directory is created with `evennia --init <name>`. In the Evennia documentation we always assume it's called `mygame`. Apart from the `server/` subfolder within, you could reorganize this folder if you preferred a different code structure for your game.
|
||||
|
||||
- `mygame/`
|
||||
- `commands/` - Overload default [Commands](Commands) or add your own Commands/[Command sets](Command-Sets) here.
|
||||
- `commands/` - Overload default [Commands](./Commands) or add your own Commands/[Command sets](./Command-Sets) here.
|
||||
- `server`/ - The structure of this folder should not change since Evennia expects it.
|
||||
- [`conf/`](https://github.com/evennia/evennia/tree/master/evennia/game_template/server) - All server configuration files sits here. The most important file is `settings.py`.
|
||||
- `logs/` - Portal log files are stored here (Server is logging to the terminal by default)
|
||||
- `typeclasses/` - this folder contains empty templates for overloading default game entities of Evennia. Evennia will automatically use the changes in those templates for the game entities it creates.
|
||||
- `web/` - This holds the [Web features](Web-Features) of your game.
|
||||
- `web/` - This holds the [Web features](./Web-Features) of your game.
|
||||
- `world/` - this is a "miscellaneous" folder holding everything related to the world you are building, such as build scripts and rules modules that don't fit with one of the other folders.
|
||||
|
||||
## Evennia library layout:
|
||||
|
||||
If you cloned the GIT repo following the instructions, you will have a folder named `evennia`. The top level of it contains Python package specific stuff such as a readme file, `setup.py` etc. It also has two subfolders`bin/` and `evennia/` (again).
|
||||
|
||||
The `bin/` directory holds OS-specific binaries that will be used when installing Evennia with `pip` as per the [Getting started](Getting-Started) instructions. The library itself is in the `evennia` subfolder. From your code you will access this subfolder simply by `import evennia`.
|
||||
The `bin/` directory holds OS-specific binaries that will be used when installing Evennia with `pip` as per the [Getting started](./Getting-Started) instructions. The library itself is in the `evennia` subfolder. From your code you will access this subfolder simply by `import evennia`.
|
||||
|
||||
- evennia
|
||||
- [`__init__.py`](Evennia-API) - The "flat API" of Evennia resides here.
|
||||
- [`commands/`](Commands) - The command parser and handler.
|
||||
- `default/` - The [default commands](Default-Command-Help) and cmdsets.
|
||||
- [`comms/`](Communications) - Systems for communicating in-game.
|
||||
- [`__init__.py`](./Evennia-API) - The "flat API" of Evennia resides here.
|
||||
- [`commands/`](./Commands) - The command parser and handler.
|
||||
- `default/` - The [default commands](./Default-Command-Help) and cmdsets.
|
||||
- [`comms/`](./Communications) - Systems for communicating in-game.
|
||||
- `contrib/` - Optional plugins too game-specific for core Evennia.
|
||||
- `game_template/` - Copied to become the "game directory" when using `evennia --init`.
|
||||
- [`help/`](Help-System) - Handles the storage and creation of help entries.
|
||||
- `locale/` - Language files ([i18n](Internationalization)).
|
||||
- [`locks/`](Locks) - Lock system for restricting access to in-game entities.
|
||||
- [`objects/`](Objects) - In-game entities (all types of items and Characters).
|
||||
- [`prototypes/`](Spawner-and-Prototypes) - Object Prototype/spawning system and OLC menu
|
||||
- [`accounts/`](Accounts) - Out-of-game Session-controlled entities (accounts, bots etc)
|
||||
- [`scripts/`](Scripts) - Out-of-game entities equivalence to Objects, also with timer support.
|
||||
- [`server/`](Portal-And-Server) - Core server code and Session handling.
|
||||
- [`help/`](./Help-System) - Handles the storage and creation of help entries.
|
||||
- `locale/` - Language files ([i18n](./Internationalization)).
|
||||
- [`locks/`](./Locks) - Lock system for restricting access to in-game entities.
|
||||
- [`objects/`](./Objects) - In-game entities (all types of items and Characters).
|
||||
- [`prototypes/`](./Spawner-and-Prototypes) - Object Prototype/spawning system and OLC menu
|
||||
- [`accounts/`](./Accounts) - Out-of-game Session-controlled entities (accounts, bots etc)
|
||||
- [`scripts/`](./Scripts) - Out-of-game entities equivalence to Objects, also with timer support.
|
||||
- [`server/`](./Portal-And-Server) - Core server code and Session handling.
|
||||
- `portal/` - Portal proxy and connection protocols.
|
||||
- [`settings_default.py`](Server-Conf#Settings-file) - Root settings of Evennia. Copy settings from here to `mygame/server/settings.py` file.
|
||||
- [`typeclasses/`](Typeclasses) - Abstract classes for the typeclass storage and database system.
|
||||
- [`utils/`](Coding-Utils) - Various miscellaneous useful coding resources.
|
||||
- [`web/`](Web-Features) - Web resources and webserver. Partly copied into game directory on initialization.
|
||||
- [`settings_default.py`](./Server-Conf#Settings-file) - Root settings of Evennia. Copy settings from here to `mygame/server/settings.py` file.
|
||||
- [`typeclasses/`](./Typeclasses) - Abstract classes for the typeclass storage and database system.
|
||||
- [`utils/`](./Coding-Utils) - Various miscellaneous useful coding resources.
|
||||
- [`web/`](./Web-Features) - Web resources and webserver. Partly copied into game directory on initialization.
|
||||
|
||||
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 (usually 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 root of the `evennia` folder has an `__init__.py` file containing the "[flat API](Evennia-API)". This holds shortcuts to various subfolders in the evennia library. It is provided to make it easier to find things; it allows you to just import `evennia` and access things from that rather than having to import from their actual locations inside the source tree.
|
||||
The root of the `evennia` folder has an `__init__.py` file containing the "[flat API](./Evennia-API)". This holds shortcuts to various subfolders in the evennia library. It is provided to make it easier to find things; it allows you to just import `evennia` and access things from that rather than having to import from their actual locations inside the source tree.
|
||||
|
|
|
|||
|
|
@ -22,15 +22,15 @@ This would help in development to quickly refer to where a resource is located.
|
|||
|
||||
### Kovitikus (Sept. 11, 2019)
|
||||
|
||||
[Batch Code](Batch-Code-Processor) should have a link in the developer area. It is currently only listed in the tutorials section as an afterthought to a tutorial title.
|
||||
[Batch Code](./Batch-Code-Processor) should have a link in the developer area. It is currently only listed in the tutorials section as an afterthought to a tutorial title.
|
||||
|
||||
***
|
||||
|
||||
In regards to the general structure of each wiki page: I'd like to see a table of contents at the top of each one, so that it can be quickly navigated and is immediately apparent what sections are covered on the page. Similar to the current [Getting Started](Getting-Started) page.
|
||||
In regards to the general structure of each wiki page: I'd like to see a table of contents at the top of each one, so that it can be quickly navigated and is immediately apparent what sections are covered on the page. Similar to the current [Getting Started](./Getting-Started) page.
|
||||
|
||||
***
|
||||
|
||||
The structuring of the page should also include a quick reference cheatsheet for certain aspects. Such as [Tags](Tags) including a quick reference section at the top that lists an example of every available method you can use in a clear and consistent format, along with a comment. Readers shouldn't have to decipher the article to gather such basic information and it should instead be available at first glance.
|
||||
The structuring of the page should also include a quick reference cheatsheet for certain aspects. Such as [Tags](./Tags) including a quick reference section at the top that lists an example of every available method you can use in a clear and consistent format, along with a comment. Readers shouldn't have to decipher the article to gather such basic information and it should instead be available at first glance.
|
||||
|
||||
Example of a quick reference:
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
## Introduction
|
||||
|
||||
An often desired feature in a MUD is to show an in-game map to help navigation. The [Static in-game map](Static-In-Game-Map) tutorial solves this by creating a *static* map, meaning the map is pre-drawn once and for all - the rooms are then created to match that map. When walking around, parts of the static map is then cut out and displayed next to the room description.
|
||||
An often desired feature in a MUD is to show an in-game map to help navigation. The [Static in-game map](./Static-In-Game-Map) tutorial solves this by creating a *static* map, meaning the map is pre-drawn once and for all - the rooms are then created to match that map. When walking around, parts of the static map is then cut out and displayed next to the room description.
|
||||
|
||||
In this tutorial we'll instead do it the other way around; We will dynamically draw the map based on the relationships we find between already existing rooms.
|
||||
|
||||
|
|
@ -12,7 +12,7 @@ In this tutorial we'll instead do it the other way around; We will dynamically d
|
|||
There are at least two requirements needed for this tutorial to work.
|
||||
|
||||
1. The structure of your mud has to follow a logical layout. Evennia supports the layout of your world to be 'logically' impossible with rooms looping to themselves or exits leading to the other side of the map. Exits can also be named anything, from "jumping out the window" to "into the fifth dimension". This tutorial assumes you can only move in the cardinal directions (N, E, S and W).
|
||||
2. Rooms must be connected and linked together for the map to be generated correctly. Vanilla Evennia comes with a admin command [@tunnel](Default-Command-Help#tunnel-cmdtunnel) that allows a user to create rooms in the cardinal directions, but additional work is needed to assure that rooms are connected. For example, if you `@tunnel east` and then immediately do `@tunnel west` you'll find that you have created two completely stand-alone rooms. So care is needed if you want to create a "logical" layout. In this tutorial we assume you have such a grid of rooms that we can generate the map from.
|
||||
2. Rooms must be connected and linked together for the map to be generated correctly. Vanilla Evennia comes with a admin command [@tunnel](./Default-Command-Help#tunnel-cmdtunnel) that allows a user to create rooms in the cardinal directions, but additional work is needed to assure that rooms are connected. For example, if you `@tunnel east` and then immediately do `@tunnel west` you'll find that you have created two completely stand-alone rooms. So care is needed if you want to create a "logical" layout. In this tutorial we assume you have such a grid of rooms that we can generate the map from.
|
||||
|
||||
## Concept
|
||||
|
||||
|
|
@ -297,7 +297,7 @@ class Room(DefaultRoom):
|
|||
|
||||
Obviously this method of generating maps doesn't take into account of any doors or exits that are hidden.. etc.. but hopefully it serves as a good base to start with. Like previously mentioned, it is very important to have a solid foundation on rooms before implementing this. You can try this on vanilla evennia by using @tunnel and essentially you can just create a long straight/edgy non-looping rooms that will show on your in-game map.
|
||||
|
||||
The above example will display the map above the room description. You could also use an [EvTable](github:evennia.utils.evtable) to place description and map next to each other. Some other things you can do is to have a [Command](Commands) that displays with a larger radius, maybe with a legend and other features.
|
||||
The above example will display the map above the room description. You could also use an [EvTable](github:evennia.utils.evtable) to place description and map next to each other. Some other things you can do is to have a [Command](./Commands) that displays with a larger radius, maybe with a legend and other features.
|
||||
|
||||
Below is the whole `map.py` for your reference. You need to update your `Room` typeclass (see above) to actually call it. Remember that to see different symbols for a location you also need to set the `sector_type` Attribute on the room to one of the keys in the `SYMBOLS` dictionary. So in this example, to make a room be mapped as `[.]` you would set the room's `sector_type` to `"SECT_INSIDE"`. Try it out with `@set here/sector_type = "SECT_INSIDE"`. If you wanted all new rooms to have a given sector symbol, you could change the default in the `SYMBOLS´ dictionary below, or you could add the Attribute in the Room's `at_object_creation` method.
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ said functions, like `{"nodename": <function>, ...}`
|
|||
## Launching the menu
|
||||
|
||||
Initializing the menu is done using a call to the `evennia.utils.evmenu.EvMenu` class. This is the
|
||||
most common way to do so - from inside a [Command](Commands):
|
||||
most common way to do so - from inside a [Command](./Commands):
|
||||
|
||||
```python
|
||||
# in, for example gamedir/commands/command.py
|
||||
|
|
@ -70,7 +70,7 @@ EvMenu(caller, menu_data,
|
|||
```
|
||||
|
||||
- `caller` (Object or Account): is a reference to the object using the menu. This object will get a
|
||||
new [CmdSet](Command-Sets) assigned to it, for handling the menu.
|
||||
new [CmdSet](./Command-Sets) assigned to it, for handling the menu.
|
||||
- `menu_data` (str, module or dict): is a module or python path to a module where the global-level
|
||||
functions will each be considered to be a menu node. Their names in the module will be the names
|
||||
by which they are referred to in the module. Importantly, function names starting with an underscore
|
||||
|
|
@ -78,7 +78,7 @@ EvMenu(caller, menu_data,
|
|||
- `startnode` (str): is the name of the menu-node to start the menu at. Changing this means that
|
||||
you can jump into a menu tree at different positions depending on circumstance and thus possibly
|
||||
re-use menu entries.
|
||||
- `cmdset_mergetype` (str): This is usually one of "Replace" or "Union" (see [CmdSets](Command-Sets).
|
||||
- `cmdset_mergetype` (str): This is usually one of "Replace" or "Union" (see [CmdSets](./Command-Sets).
|
||||
The first means that the menu is exclusive - the user has no access to any other commands while
|
||||
in the menu. The Union mergetype means the menu co-exists with previous commands (and may overload
|
||||
them, so be careful as to what to name your menu entries in this case).
|
||||
|
|
@ -99,7 +99,7 @@ EvMenu(caller, menu_data,
|
|||
- `startnode_input` (str or (str, dict) tuple): Pass an input text or a input text + kwargs to the
|
||||
start node as if it was entered on a fictional previous node. This can be very useful in order to
|
||||
start a menu differently depending on the Command's arguments in which it was initialized.
|
||||
- `session` (Session): Useful when calling the menu from an [Account](Accounts) in
|
||||
- `session` (Session): Useful when calling the menu from an [Account](./Accounts) in
|
||||
`MULTISESSION_MODDE` higher than 2, to make sure only the right Session sees the menu output.
|
||||
- `debug` (bool): If set, the `menudebug` command will be made available in the menu. Use it to
|
||||
list the current state of the menu and use `menudebug <variable>` to inspect a specific state
|
||||
|
|
@ -414,14 +414,14 @@ See `evennia/utils/evmenu.py` for the details of their default implementations.
|
|||
|
||||
## Examples:
|
||||
|
||||
- **[Simple branching menu](EvMenu#example-simple-branching-menu)** - choose from options
|
||||
- **[Dynamic goto](EvMenu#example-dynamic-goto)** - jumping to different nodes based on response
|
||||
- **[Set caller properties](EvMenu#example-set-caller-properties)** - a menu that changes things
|
||||
- **[Getting arbitrary input](EvMenu#example-get-arbitrary-input)** - entering text
|
||||
- **[Storing data between nodes](EvMenu#example-storing-data-between-nodes)** - keeping states and information while in the menu
|
||||
- **[Repeating the same node](EvMenu#example-repeating-the-same-node)** - validating within the node before moving to the next
|
||||
- **[Full Menu](EvMenu#example-full-menu):** a complete example
|
||||
- **[Yes/No prompt](EvMenu#example-yesno-prompt)** - entering text with limited possible responses (this is *not* using EvMenu but the conceptually similar yet technically unrelated `get_input` helper function accessed as `evennia.utils.evmenu.get_input`).
|
||||
- **[Simple branching menu](./EvMenu#example-simple-branching-menu)** - choose from options
|
||||
- **[Dynamic goto](./EvMenu#example-dynamic-goto)** - jumping to different nodes based on response
|
||||
- **[Set caller properties](./EvMenu#example-set-caller-properties)** - a menu that changes things
|
||||
- **[Getting arbitrary input](./EvMenu#example-get-arbitrary-input)** - entering text
|
||||
- **[Storing data between nodes](./EvMenu#example-storing-data-between-nodes)** - keeping states and information while in the menu
|
||||
- **[Repeating the same node](./EvMenu#example-repeating-the-same-node)** - validating within the node before moving to the next
|
||||
- **[Full Menu](./EvMenu#example-full-menu):** a complete example
|
||||
- **[Yes/No prompt](./EvMenu#example-yesno-prompt)** - entering text with limited possible responses (this is *not* using EvMenu but the conceptually similar yet technically unrelated `get_input` helper function accessed as `evennia.utils.evmenu.get_input`).
|
||||
|
||||
|
||||
### Example: Simple branching menu
|
||||
|
|
@ -488,7 +488,7 @@ def enter_guild:
|
|||
|
||||
This simple callable goto will analyse what happens depending on who the `caller` is. The
|
||||
`enter_guild` node will give you a choice of what to say to the guard. If you try to enter, you will
|
||||
end up in different nodes depending on (in this example) if you have the right [Tag](Tags) set on
|
||||
end up in different nodes depending on (in this example) if you have the right [Tag](./Tags) set on
|
||||
yourself or not. Note that since we don't include any 'key's in the option dictionary, you will just
|
||||
get to pick between numbers.
|
||||
|
||||
|
|
@ -785,7 +785,7 @@ function - for example you can't use other Python keywords like `if` inside the
|
|||
|
||||
Unless you are dealing with a relatively simple dynamic menu, defining menus with lambda's is
|
||||
probably more work than it's worth: You can create dynamic menus by instead making each node
|
||||
function more clever. See the [NPC shop tutorial](NPC-shop-Tutorial) for an example of this.
|
||||
function more clever. See the [NPC shop tutorial](./NPC-shop-Tutorial) for an example of this.
|
||||
|
||||
|
||||
## Ask for simple input
|
||||
|
|
@ -973,8 +973,8 @@ auto-created by the `list_node` decorator.
|
|||
|
||||
## Assorted notes
|
||||
|
||||
The EvMenu is implemented using [Commands](Commands). When you start a new EvMenu, the user of the
|
||||
menu will be assigned a [CmdSet](Command-Sets) with the commands they need to navigate the menu.
|
||||
The EvMenu is implemented using [Commands](./Commands). When you start a new EvMenu, the user of the
|
||||
menu will be assigned a [CmdSet](./Command-Sets) with the commands they need to navigate the menu.
|
||||
This means that if you were to, from inside the menu, assign a new command set to the caller, *you
|
||||
may override the Menu Cmdset and kill the menu*. If you want to assign cmdsets to the caller as part
|
||||
of the menu, you should store the cmdset on `caller.ndb._menutree` and wait to actually assign it
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ from evennia.utils import evmore
|
|||
|
||||
evmore.msg(receiver, long_text)
|
||||
```
|
||||
Where receiver is an [Object](Objects) or a [Account](Accounts). If the text is longer than the
|
||||
Where receiver is an [Object](./Objects) or a [Account](./Accounts). If the text is longer than the
|
||||
client's screen height (as determined by the NAWS handshake or by `settings.CLIENT_DEFAULT_HEIGHT`)
|
||||
the pager will show up, something like this:
|
||||
|
||||
|
|
|
|||
|
|
@ -10,13 +10,13 @@ What we *do* however, is to provide a solid foundation for all the boring databa
|
|||
|
||||
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 is 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](Soft-Code) 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.
|
||||
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](./Soft-Code) 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.
|
||||
|
||||
## Can I test it somewhere?
|
||||
|
||||
Evennia's demo server can be found at [demo.evennia.com](http://demo.evennia.com). If you prefer to connect to the demo via your own telnet client you can do so at `silvren.com`, port `4280`. Here is a [screenshot](Screenshot).
|
||||
Evennia's demo server can be found at [demo.evennia.com](http://demo.evennia.com). If you prefer to connect to the demo via your own telnet client you can do so at `silvren.com`, port `4280`. Here is a [screenshot](./Screenshot).
|
||||
|
||||
Once you installed Evennia yourself it comes with its own tutorial - this shows off some of the possibilities _and_ gives you a small single-player quest to play. The tutorial takes only one single in-game command to install as explained [here](Tutorial-World-Introduction).
|
||||
Once you installed Evennia yourself it comes with its own tutorial - this shows off some of the possibilities _and_ gives you a small single-player quest to play. The tutorial takes only one single in-game command to install as explained [here](./Tutorial-World-Introduction).
|
||||
|
||||
## Brief summary of features
|
||||
|
||||
|
|
@ -54,11 +54,11 @@ Once you installed Evennia yourself it comes with its own tutorial - this shows
|
|||
- RSS feeds can be echoed to in-game channels (things like Twitter can easily be added)
|
||||
- Several different databases supported (SQLite3, MySQL, PostgreSQL, ...)
|
||||
|
||||
For more extensive feature information, see the [Developer Central](Developer-Central).
|
||||
For more extensive feature information, see the [Developer Central](./Developer-Central).
|
||||
|
||||
## What you need to know to work with Evennia
|
||||
|
||||
Assuming you have Evennia working (see the [quick start instructions](Getting-Started)) 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.
|
||||
Assuming you have Evennia working (see the [quick start instructions](./Getting-Started)) 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!
|
||||
|
||||
|
|
@ -67,7 +67,7 @@ Evennia comes with a default set of commands for the Python newbies and for thos
|
|||
### I know basic Python, or I am willing to learn
|
||||
|
||||
Evennia's source code is extensively documented and is [viewable online](https://github.com/evennia/evennia). We also have a comprehensive [online manual](https://github.com/evennia/evennia/wiki) with lots of examples. But while Python is considered a very easy programming language to get into, you do have a learning curve to climb if you are new to programming. You should probably sit down
|
||||
with a Python beginner's [tutorial](http://docs.python.org/tutorial/) (there are plenty of them on the web if you look around) so you at least know what you are seeing. See also our [link page](Links#wiki-litterature) for some reading suggestions. 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:
|
||||
with a Python beginner's [tutorial](http://docs.python.org/tutorial/) (there are plenty of them on the web if you look around) so you at least know what you are seeing. See also our [link page](./Links#wiki-litterature) for some reading suggestions. 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 and using python [modules](http://docs.python.org/3.7/tutorial/modules.html)
|
||||
- Using [variables](http://www.tutorialspoint.com/python/python_variable_types.htm), [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)
|
||||
|
|
@ -75,7 +75,7 @@ with a Python beginner's [tutorial](http://docs.python.org/tutorial/) (there are
|
|||
- Doing [string handling and formatting](http://docs.python.org/tutorial/introduction.html#strings)
|
||||
- Have a basic understanding of [object-oriented programming](http://www.tutorialspoint.com/python/python_classes_objects.htm), 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), create custom [Objects](Objects) as well as make your world come alive with basic [Scripts](Scripts). You can definitely build a whole advanced and customized game from extending Evennia's examples only.
|
||||
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), create custom [Objects](./Objects) as well as make your world come alive with basic [Scripts](./Scripts). You can definitely build a whole advanced and customized game from extending Evennia's examples only.
|
||||
|
||||
### I know my Python stuff and I am willing to use it!
|
||||
|
||||
|
|
@ -85,10 +85,10 @@ If you *also* happen to know some web programming (HTML, CSS, Javascript) there
|
|||
|
||||
### Where to from here?
|
||||
|
||||
From here you can continue browsing the [online documentation]([online documentation](index)) to find more info about Evennia. Or you can jump into the [Tutorials](Tutorials) and get your hands dirty with code right away. You can also read the developer's [dev blog](https://evennia.blogspot.com/) for many tidbits and snippets about Evennia's development and structure.
|
||||
From here you can continue browsing the [online documentation]([online documentation](index)) to find more info about Evennia. Or you can jump into the [Tutorials](./Tutorials) and get your hands dirty with code right away. You can also read the developer's [dev blog](https://evennia.blogspot.com/) for many tidbits and snippets about Evennia's development and structure.
|
||||
|
||||
Some more hints:
|
||||
|
||||
1. Get engaged in the community. Make an introductory post to our [mailing list/forum](https://groups.google.com/forum/#!forum/evennia) and get to know people. It's also highly recommended you hop onto our [Developer chat](http://webchat.freenode.net/?channels=evennia&uio=MT1mYWxzZSY5PXRydWUmMTE9MTk1JjEyPXRydWUbb) on IRC. This allows you to chat directly with other developers new and old as well as with the devs of Evennia itself. This chat is logged (you can find links on http://www.evennia.com) and can also be searched from the same place for discussion topics you are interested in.
|
||||
2. Read the [Game Planning](Game-Planning) wiki page. It gives some ideas for your work flow and the state of mind you should aim for - including cutting down the scope of your game for its first release.
|
||||
3. Do the [Tutorial for basic MUSH-like game](Tutorial-for-basic-MUSH-like-game) carefully from beginning to end and try to understand what does what. Even if you are not interested in a MUSH for your own game, you will end up with a small (very small) game that you can build or learn from.
|
||||
2. Read the [Game Planning](./Game-Planning) wiki page. It gives some ideas for your work flow and the state of mind you should aim for - including cutting down the scope of your game for its first release.
|
||||
3. Do the [Tutorial for basic MUSH-like game](./Tutorial-for-basic-MUSH-like-game) carefully from beginning to end and try to understand what does what. Even if you are not interested in a MUSH for your own game, you will end up with a small (very small) game that you can build or learn from.
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ In MUSH, users tend to code and expand all aspects of the game from inside it us
|
|||
|
||||
## Collaborating on a game - Python vs Softcode
|
||||
|
||||
For a *Player*, collaborating on a game need not be too different between MUSH and Evennia. The building and description of the game world can still happen mostly in-game using build commands, using text tags and [inline functions](TextTags#inline-functions) to prettify and customize the experience. Evennia offers external ways to build a world but those are optional. There is also nothing *in principle* stopping a Developer from offering a softcode-like language to Players if that is deemed necessary.
|
||||
For a *Player*, collaborating on a game need not be too different between MUSH and Evennia. The building and description of the game world can still happen mostly in-game using build commands, using text tags and [inline functions](./TextTags#inline-functions) to prettify and customize the experience. Evennia offers external ways to build a world but those are optional. There is also nothing *in principle* stopping a Developer from offering a softcode-like language to Players if that is deemed necessary.
|
||||
|
||||
For *Developers* of the game, the difference is larger: Code is mainly written outside the game in Python modules rather than in-game on the command line. Python is a very popular and well-supported language with tons of documentation and help to be found. The Python standard library is also a great help for not having to reinvent the wheel. But that said, while Python is considered one of the easier languages to learn and use it is undoubtedly very different from MUSH softcode.
|
||||
|
||||
|
|
@ -34,7 +34,7 @@ if you are new to object oriented design it's important to note that all object
|
|||
|
||||
The `@spawn` command allows one to conveniently choose between different "sets" of Attributes to put on each new Orc (like the "warrior" set or "shaman" set) . Such sets can even inherit one another which is again somewhat remniscent at least of the *effect* of `@parent` and the object-based inheritance of MUSH.
|
||||
|
||||
There are other differences for sure, but that should give some feel for things. Enough with the theory. Let's get down to more practical matters next. To install, see the [Getting Started instructions](Getting-Started).
|
||||
There are other differences for sure, but that should give some feel for things. Enough with the theory. Let's get down to more practical matters next. To install, see the [Getting Started instructions](./Getting-Started).
|
||||
|
||||
## A first step making things more familiar
|
||||
|
||||
|
|
@ -119,8 +119,8 @@ With the `nick` functionality players can mitigate a lot of syntax dislikes even
|
|||
|
||||
## Next steps
|
||||
|
||||
If you are a *Developer* and are interested in making a more MUSH-like Evennia game, a good start is to look into the Evennia [Tutorial for a first MUSH-like game](Tutorial-for-basic-MUSH-like-game). That steps through building a simple little game from scratch and helps to acquaint you with the various corners of Evennia. There is also the [Tutorial for running roleplaying sessions](Evennia-for-roleplaying-sessions) that can be of interest.
|
||||
If you are a *Developer* and are interested in making a more MUSH-like Evennia game, a good start is to look into the Evennia [Tutorial for a first MUSH-like game](./Tutorial-for-basic-MUSH-like-game). That steps through building a simple little game from scratch and helps to acquaint you with the various corners of Evennia. There is also the [Tutorial for running roleplaying sessions](./Evennia-for-roleplaying-sessions) that can be of interest.
|
||||
|
||||
An important aspect of making things more familiar for *Players* is adding new and tweaking existing commands. How this is done is covered by the [Tutorial on adding new commands](Adding-Command-Tutorial). You may also find it useful to shop through the `evennia/contrib/` folder. The [Tutorial world](Tutorial-World-Introduction) is a small single-player quest you can try (it’s not very MUSH-like but it does show many Evennia concepts in action). Beyond that there are [many more tutorials](Tutorials) to try out. If you feel you want a more visual overview you can also look at [Evennia in pictures](https://evennia.blogspot.se/2016/05/evennia-in-pictures.html).
|
||||
An important aspect of making things more familiar for *Players* is adding new and tweaking existing commands. How this is done is covered by the [Tutorial on adding new commands](./Adding-Command-Tutorial). You may also find it useful to shop through the `evennia/contrib/` folder. The [Tutorial world](./Tutorial-World-Introduction) is a small single-player quest you can try (it’s not very MUSH-like but it does show many Evennia concepts in action). Beyond that there are [many more tutorials](./Tutorials) to try out. If you feel you want a more visual overview you can also look at [Evennia in pictures](https://evennia.blogspot.se/2016/05/evennia-in-pictures.html).
|
||||
|
||||
… And of course, if you need further help you can always drop into the [Evennia chatroom](http://webchat.freenode.net/?channels=evennia&uio=MT1mYWxzZSY5PXRydWUmMTE9MTk1JjEyPXRydWUbb) or post a question in our [forum/mailing list](https://groups.google.com/forum/#%21forum/evennia)!
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ We will find most of these things are already part of vanilla Evennia, but that
|
|||
|
||||
## Starting out
|
||||
|
||||
We will assume you start from scratch. You need Evennia installed, as per the [Getting Started](Getting-Started) instructions. Initialize a new game directory with `evennia init <gamedirname>`. In this tutorial we assume your game dir is simply named `mygame`. You can use the default database and keep all other settings to default for now. Familiarize yourself with the `mygame` folder before continuing. You might want to browse the [First Steps Coding](First-Steps-Coding) tutorial, just to see roughly where things are modified.
|
||||
We will assume you start from scratch. You need Evennia installed, as per the [Getting Started](./Getting-Started) instructions. Initialize a new game directory with `evennia init <gamedirname>`. In this tutorial we assume your game dir is simply named `mygame`. You can use the default database and keep all other settings to default for now. Familiarize yourself with the `mygame` folder before continuing. You might want to browse the [First Steps Coding](./First-Steps-Coding) tutorial, just to see roughly where things are modified.
|
||||
|
||||
## The Game Master role
|
||||
|
||||
|
|
@ -28,7 +28,7 @@ In brief:
|
|||
|
||||
### The permission hierarchy
|
||||
|
||||
Evennia has the following [permission hierarchy](Building-Permissions#assigning-permissions) out of the box: *Players, Helpers, Builders, Admins* and finally *Developers*. We could change these but then we'd need to update our Default commands to use the changes. We want to keep this simple, so instead we map our different roles on top of this permission ladder.
|
||||
Evennia has the following [permission hierarchy](./Building-Permissions#assigning-permissions) out of the box: *Players, Helpers, Builders, Admins* and finally *Developers*. We could change these but then we'd need to update our Default commands to use the changes. We want to keep this simple, so instead we map our different roles on top of this permission ladder.
|
||||
|
||||
1. `Players` is the permission set on normal players. This is the default for anyone creating a new account on the server.
|
||||
2. `Helpers` are like `Players` except they also have the ability to create/edit new help entries. This could be granted to players who are willing to help with writing lore or custom logs for everyone.
|
||||
|
|
@ -36,7 +36,7 @@ Evennia has the following [permission hierarchy](Building-Permissions#assigning-
|
|||
4. `Admins` is the permission level the GM should have. Admins can do everything builders can (create/describe rooms etc) but also kick accounts, rename them and things like that.
|
||||
5. `Developers`-level permission are the server administrators, the ones with the ability to restart/shutdown the server as well as changing the permission levels.
|
||||
|
||||
> The [superuser](Building-Permissions#the-super-user) is not part of the hierarchy and actually completely bypasses it. We'll assume server admin(s) will "just" be Developers.
|
||||
> The [superuser](./Building-Permissions#the-super-user) is not part of the hierarchy and actually completely bypasses it. We'll assume server admin(s) will "just" be Developers.
|
||||
|
||||
### How to grant permissions
|
||||
|
||||
|
|
@ -69,7 +69,7 @@ So let's make this possible. This is what we'll do:
|
|||
|
||||
#### Character modification
|
||||
|
||||
Let's first start by customizing the Character. We recommend you browse the beginning of the [Account](Accounts) page to make sure you know how Evennia differentiates between the OOC "Account objects" (not to be confused with the `Accounts` permission, which is just a string specifying your access) and the IC "Character objects".
|
||||
Let's first start by customizing the Character. We recommend you browse the beginning of the [Account](./Accounts) page to make sure you know how Evennia differentiates between the OOC "Account objects" (not to be confused with the `Accounts` permission, which is just a string specifying your access) and the IC "Character objects".
|
||||
|
||||
Open `mygame/typeclasses/characters.py` and modify the default `Character` class:
|
||||
|
||||
|
|
@ -103,13 +103,13 @@ class Character(DefaultCharacter):
|
|||
|
||||
```
|
||||
|
||||
Above, we change how the Character's name is displayed: If the account controlling this Character is a GM, we attach the string `(GM)` to the Character's name so everyone can tell who's the boss. If we ourselves are Developers or GM's we will see database ids attached to Characters names, which can help if doing database searches against Characters of exactly the same name. We base the "gm-ingness" on having an flag (an [Attribute](Attributes)) named `is_gm`. We'll make sure new GM's actually get this flag below.
|
||||
Above, we change how the Character's name is displayed: If the account controlling this Character is a GM, we attach the string `(GM)` to the Character's name so everyone can tell who's the boss. If we ourselves are Developers or GM's we will see database ids attached to Characters names, which can help if doing database searches against Characters of exactly the same name. We base the "gm-ingness" on having an flag (an [Attribute](./Attributes)) named `is_gm`. We'll make sure new GM's actually get this flag below.
|
||||
|
||||
> **Extra exercise:** This will only show the `(GM)` text on *Characters* puppeted by a GM account, that is, it will show only to those in the same location. If we wanted it to also pop up in, say, `who` listings and channels, we'd need to make a similar change to the `Account` typeclass in `mygame/typeclasses/accounts.py`. We leave this as an exercise to the reader.
|
||||
|
||||
#### New @gm/@ungm command
|
||||
|
||||
We will describe in some detail how to create and add an Evennia [command](Commands) here with the hope that we don't need to be as detailed when adding commands in the future. We will build on Evennia's default "mux-like" commands here.
|
||||
We will describe in some detail how to create and add an Evennia [command](./Commands) here with the hope that we don't need to be as detailed when adding commands in the future. We will build on Evennia's default "mux-like" commands here.
|
||||
|
||||
Open `mygame/commands/command.py` and add a new Command class at the bottom:
|
||||
|
||||
|
|
@ -211,7 +211,7 @@ In brief:
|
|||
|
||||
There are many ways to build a Character sheet in text, from manually pasting strings together to more automated ways. Exactly what is the best/easiest way depends on the sheet one tries to create. We will here show two examples using the *EvTable* and *EvForm* utilities.Later we will create Commands to edit and display the output from those utilities.
|
||||
|
||||
> Note that due to the limitations of the wiki, no color is used in any of the examples. See [the text tag documentation](TextTags) for how to add color to the tables and forms.
|
||||
> Note that due to the limitations of the wiki, no color is used in any of the examples. See [the text tag documentation](./TextTags) for how to add color to the tables and forms.
|
||||
|
||||
#### Making a sheet with EvTable
|
||||
|
||||
|
|
@ -581,7 +581,7 @@ Use `help dice` to see what syntax is supported or look at `evennia/contrib/dice
|
|||
|
||||
## Rooms
|
||||
|
||||
Evennia comes with rooms out of the box, so no extra work needed. A GM will automatically have all needed building commands available. A fuller go-through is found in the [Building tutorial](Building-Quickstart). Here are some useful highlights:
|
||||
Evennia comes with rooms out of the box, so no extra work needed. A GM will automatically have all needed building commands available. A fuller go-through is found in the [Building tutorial](./Building-Quickstart). Here are some useful highlights:
|
||||
|
||||
* `@dig roomname;alias = exit_there;alias, exit_back;alias` - this is the basic command for digging a new room. You can specify any exit-names and just enter the name of that exit to go there.
|
||||
* `@tunnel direction = roomname` - this is a specialized command that only accepts directions in the cardinal directions (n,ne,e,se,s,sw,w,nw) as well as in/out and up/down. It also automatically builds "matching" exits back in the opposite direction.
|
||||
|
|
@ -594,7 +594,7 @@ Evennia comes with rooms out of the box, so no extra work needed. A GM will auto
|
|||
|
||||
## Channels
|
||||
|
||||
Evennia comes with [Channels](Communications#Channels) in-built and they are described fully in the documentation. For brevity, here are the relevant commands for normal use:
|
||||
Evennia comes with [Channels](./Communications#Channels) in-built and they are described fully in the documentation. For brevity, here are the relevant commands for normal use:
|
||||
|
||||
* `@ccreate new_channel;alias;alias = short description` - Creates a new channel.
|
||||
* `addcom channel` - join an existing channel. Use `addcom alias = channel` to add a new alias you can use to talk to the channel, as many as desired.
|
||||
|
|
|
|||
|
|
@ -12,10 +12,10 @@ A few local variables are made available when running `@py`. These offer entry i
|
|||
|
||||
- **self** / **me** - the calling object (i.e. you)
|
||||
- **here** - the current caller's location
|
||||
- **obj** - a dummy [Object](Objects) instance
|
||||
- **evennia** - Evennia's [flat API](Evennia-API) - through this you can access all of Evennia.
|
||||
- **obj** - a dummy [Object](./Objects) instance
|
||||
- **evennia** - Evennia's [flat API](./Evennia-API) - through this you can access all of Evennia.
|
||||
|
||||
For accessing other objects in the same room you need to use `self.search(name)`. For objects in other locations, use one of the `evennia.search_*` methods. See [below](Execute-Python-Code#finding-objects).
|
||||
For accessing other objects in the same room you need to use `self.search(name)`. For objects in other locations, use one of the `evennia.search_*` methods. See [below](./Execute-Python-Code#finding-objects).
|
||||
|
||||
## Returning output
|
||||
|
||||
|
|
@ -30,7 +30,7 @@ Note that we didn't get any return value, all we where told is that the code fin
|
|||
09:15
|
||||
<<< Done.
|
||||
|
||||
> Warning: When using the `msg` function wrap our argument in `str()` to convert it into a string above. This is not strictly necessary for most types of data (Evennia will usually convert to a string behind the scenes for you). But for *lists* and *tuples* you will be confused by the output if you don't wrap them in `str()`: only the first item of the iterable will be returned. This is because doing `msg(text)` is actually just a convenience shortcut; the full argument that `msg` accepts is something called an *outputfunc* on the form `(cmdname, (args), {kwargs})` (see [the message path](Messagepath) for more info). Sending a list/tuple confuses Evennia to think you are sending such a structure. Converting it to a string however makes it clear it should just be displayed as-is.
|
||||
> Warning: When using the `msg` function wrap our argument in `str()` to convert it into a string above. This is not strictly necessary for most types of data (Evennia will usually convert to a string behind the scenes for you). But for *lists* and *tuples* you will be confused by the output if you don't wrap them in `str()`: only the first item of the iterable will be returned. This is because doing `msg(text)` is actually just a convenience shortcut; the full argument that `msg` accepts is something called an *outputfunc* on the form `(cmdname, (args), {kwargs})` (see [the message path](./Messagepath) for more info). Sending a list/tuple confuses Evennia to think you are sending such a structure. Converting it to a string however makes it clear it should just be displayed as-is.
|
||||
|
||||
If you were to use Python's standard `print`, you will see the result in your current `stdout` (your terminal by default, otherwise your log file).
|
||||
|
||||
|
|
@ -85,4 +85,4 @@ It's recommended that you get a more fully featured Python interpreter like [iPy
|
|||
In [2]: evennia.managers.objects.all()
|
||||
Out[3]: [<ObjectDB: Harry>, <ObjectDB: Limbo>, ...]
|
||||
|
||||
See the page about the [Evennia-API](Evennia-API) for more things to explore.
|
||||
See the page about the [Evennia-API](./Evennia-API) for more things to explore.
|
||||
|
|
|
|||
|
|
@ -3,16 +3,16 @@
|
|||
|
||||
This section gives a brief step-by-step introduction on how to set up Evennia for the first time so you can modify and overload the defaults easily. You should only need to do these steps once. It also walks through you making your first few tweaks.
|
||||
|
||||
Before continuing, make sure you have Evennia installed and running by following the [Getting Started](Getting-Started) instructions. You should have initialized a new game folder with the `evennia --init foldername` command. We will in the following assume this folder is called "mygame".
|
||||
Before continuing, make sure you have Evennia installed and running by following the [Getting Started](./Getting-Started) instructions. You should have initialized a new game folder with the `evennia --init foldername` command. We will in the following assume this folder is called "mygame".
|
||||
|
||||
It might be a good idea to eye through the brief [Coding Introduction](Coding-Introduction) too (especially the recommendations in the section about the evennia "flat" API and about using `evennia shell` will help you here and in the future).
|
||||
It might be a good idea to eye through the brief [Coding Introduction](./Coding-Introduction) too (especially the recommendations in the section about the evennia "flat" API and about using `evennia shell` will help you here and in the future).
|
||||
|
||||
To follow this tutorial you also need to know the basics of operating your computer's terminal/command line. You also need to have a text editor to edit and create source text files. There are plenty of online tutorials on how to use the terminal and plenty of good free text editors. We will assume these things are already familiar to you henceforth.
|
||||
|
||||
|
||||
## Your First Changes
|
||||
|
||||
Below are some first things to try with your new custom modules. You can test these to get a feel for the system. See also [Tutorials](Tutorials) for more step-by-step help and special cases.
|
||||
Below are some first things to try with your new custom modules. You can test these to get a feel for the system. See also [Tutorials](./Tutorials) for more step-by-step help and special cases.
|
||||
|
||||
### Tweak Default Character
|
||||
|
||||
|
|
@ -43,11 +43,11 @@ We will add some simple rpg attributes to our default Character. In the next sec
|
|||
return self.db.strength, self.db.agility, self.db.magic
|
||||
```
|
||||
|
||||
1. [Reload](Start-Stop-Reload) the server (you will still be connected to the game after doing this). Note that if you examine *yourself* you will *not* see any new Attributes appear yet. Read the next section to understand why.
|
||||
1. [Reload](./Start-Stop-Reload) the server (you will still be connected to the game after doing this). Note that if you examine *yourself* you will *not* see any new Attributes appear yet. Read the next section to understand why.
|
||||
|
||||
#### Updating Yourself
|
||||
|
||||
It's important to note that the new [Attributes](Attributes) we added above will only be stored on *newly* created characters. The reason for this is simple: The `at_object_creation` method, where we added those Attributes, is per definition only called when the object is *first created*, then never again. This is usually a good thing since those Attributes may change over time - calling that hook would reset them back to start values. But it also means that your existing character doesn't have them yet. You can see this by calling the `get_abilities` hook on yourself at this point:
|
||||
It's important to note that the new [Attributes](./Attributes) we added above will only be stored on *newly* created characters. The reason for this is simple: The `at_object_creation` method, where we added those Attributes, is per definition only called when the object is *first created*, then never again. This is usually a good thing since those Attributes may change over time - calling that hook would reset them back to start values. But it also means that your existing character doesn't have them yet. You can see this by calling the `get_abilities` hook on yourself at this point:
|
||||
|
||||
```
|
||||
# (you have to be superuser to use @py)
|
||||
|
|
@ -84,7 +84,7 @@ Using `swap_typeclass` to the same typeclass we already have will re-run the cre
|
|||
@py typeclasses.myclass import MyClass;[obj.swap_typeclass(MyClass) for obj in MyClass.objects.all()]
|
||||
```
|
||||
|
||||
See the [Object Typeclass tutorial](Adding-Object-Typeclass-Tutorial) for more help and the [Typeclasses](Typeclasses) and [Attributes](Attributes) page for detailed documentation about Typeclasses and Attributes.
|
||||
See the [Object Typeclass tutorial](./Adding-Object-Typeclass-Tutorial) for more help and the [Typeclasses](./Typeclasses) and [Attributes](./Attributes) page for detailed documentation about Typeclasses and Attributes.
|
||||
|
||||
#### Troubleshooting: Updating Yourself
|
||||
|
||||
|
|
@ -110,7 +110,7 @@ The full error will show in the terminal/console but this is confusing since you
|
|||
|
||||
### Add a New Default Command
|
||||
|
||||
The `@py` command used above is only available to privileged users. We want any player to be able to see their stats. Let's add a new [command](Commands) to list the abilities we added in the previous section.
|
||||
The `@py` command used above is only available to privileged users. We want any player to be able to see their stats. Let's add a new [command](./Commands) to list the abilities we added in the previous section.
|
||||
|
||||
1. Open `mygame/commands/command.py`. You could in principle put your command anywhere but this module has all the imports already set up along with some useful documentation. Make a new class at the bottom of this file:
|
||||
|
||||
|
|
@ -149,7 +149,7 @@ The `@py` command used above is only available to privileged users. We want any
|
|||
self.add(CmdAbilities())
|
||||
```
|
||||
|
||||
1. [Reload](Start-Stop-Reload) the server (noone will be disconnected by doing this).
|
||||
1. [Reload](./Start-Stop-Reload) the server (noone will be disconnected by doing this).
|
||||
|
||||
You (and anyone else) should now be able to use `abilities` (or its alias `abi`) as part of your normal commands in-game:
|
||||
|
||||
|
|
@ -158,7 +158,7 @@ abilities
|
|||
STR: 5, AGI: 4, MAG: 2
|
||||
```
|
||||
|
||||
See the [Adding a Command tutorial](Adding-Command-Tutorial) for more examples and the [Commands](Commands) section for detailed documentation about the Command system.
|
||||
See the [Adding a Command tutorial](./Adding-Command-Tutorial) for more examples and the [Commands](./Commands) section for detailed documentation about the Command system.
|
||||
|
||||
### Make a New Type of Object
|
||||
|
||||
|
|
@ -204,9 +204,9 @@ Let's test to make a new type of object. This example is an "wise stone" object
|
|||
return string + wisewords
|
||||
```
|
||||
|
||||
1. Check your code for bugs. Tracebacks will appear on your command line or log. If you have a grave Syntax Error in your code, the source file itself will fail to load which can cause issues with the entire cmdset. If so, fix your bug and [reload the server from the command line](Start-Stop-Reload) (noone will be disconnected by doing this).
|
||||
1. Check your code for bugs. Tracebacks will appear on your command line or log. If you have a grave Syntax Error in your code, the source file itself will fail to load which can cause issues with the entire cmdset. If so, fix your bug and [reload the server from the command line](./Start-Stop-Reload) (noone will be disconnected by doing this).
|
||||
1. Use `@create/drop stone:wiseobject.WiseObject` to create a talkative stone. If the `@create` command spits out a warning or cannot find the typeclass (it will tell you which paths it searched), re-check your code for bugs and that you gave the correct path. The `@create` command starts looking for Typeclasses in `mygame/typeclasses/`.
|
||||
1. Use `look stone` to test. You will see the default description ("You see nothing special") followed by a random message of stony wisdom. Use `@desc stone = This is a wise old stone.` to make it look nicer. See the [Builder Docs](Builder-Docs) for more information.
|
||||
1. Use `look stone` to test. You will see the default description ("You see nothing special") followed by a random message of stony wisdom. Use `@desc stone = This is a wise old stone.` to make it look nicer. See the [Builder Docs](./Builder-Docs) for more information.
|
||||
|
||||
Note that `at_object_creation` is only called once, when the stone is first created. If you make changes to this method later, already existing stones will not see those changes. As with the `Character` example above you can use `@typeclass/force` to tell the stone to re-run its initialization.
|
||||
|
||||
|
|
@ -214,4 +214,4 @@ The `at_object_creation` is a special case though. Changing most other aspects o
|
|||
|
||||
## Where to Go From Here?
|
||||
|
||||
There are more [Tutorials](Tutorials), including one for building a [whole little MUSH-like game](Tutorial-for-basic-MUSH-like-game) - that is instructive also if you have no interest in MUSHes per se. A good idea is to also get onto the [IRC chat](http://webchat.freenode.net/?channels=evennia) and the [mailing list](https://groups.google.com/forum/#!forum/evennia) to get in touch with the community and other developers.
|
||||
There are more [Tutorials](./Tutorials), including one for building a [whole little MUSH-like game](./Tutorial-for-basic-MUSH-like-game) - that is instructive also if you have no interest in MUSHes per se. A good idea is to also get onto the [IRC chat](http://webchat.freenode.net/?channels=evennia) and the [mailing list](https://groups.google.com/forum/#!forum/evennia) to get in touch with the community and other developers.
|
||||
|
|
|
|||
|
|
@ -75,13 +75,13 @@ A MUD's a lot more involved than you would think and these things hang together
|
|||
|
||||
This is the actual work of creating the "game" part of your game. Many "game-designer" types tend to gloss over this bit and jump directly to **World Building**. Vice versa, many "game-coder" types tend to jump directly to this part without doing the **Planning** first. Neither way is good and *will* lead to you having to redo all your hard work at least once, probably more.
|
||||
|
||||
Evennia's [Developer Central](Developer-Central) tries to help you with this bit of development. We also have a slew of [Tutorials](Tutorials) with worked examples. Evennia tries hard to make this part easier for you, but there is no way around the fact that if you want anything but a very basic Talker-type game you *will* have to bite the bullet and code your game (or find a coder willing to do it for you).
|
||||
Evennia's [Developer Central](./Developer-Central) tries to help you with this bit of development. We also have a slew of [Tutorials](./Tutorials) with worked examples. Evennia tries hard to make this part easier for you, but there is no way around the fact that if you want anything but a very basic Talker-type game you *will* have to bite the bullet and code your game (or find a coder willing to do it for you).
|
||||
|
||||
Even if you won't code anything yourself, as a designer you need to at least understand the basic paradigms of Evennia, such as [Objects](Objects), [Commands](Commands) and [Scripts](Scripts) and how they hang together. We recommend you go through the [Tutorial World](Tutorial-World-Introduction) in detail (as well as glancing at its code) to get at least a feel for what is involved behind the scenes. You could also look through the tutorial for [building a game from scratch](Tutorial-for-basic-MUSH-like-game).
|
||||
Even if you won't code anything yourself, as a designer you need to at least understand the basic paradigms of Evennia, such as [Objects](./Objects), [Commands](./Commands) and [Scripts](./Scripts) and how they hang together. We recommend you go through the [Tutorial World](./Tutorial-World-Introduction) in detail (as well as glancing at its code) to get at least a feel for what is involved behind the scenes. You could also look through the tutorial for [building a game from scratch](./Tutorial-for-basic-MUSH-like-game).
|
||||
|
||||
During Coding you look back at the things you wanted during the **Planning** phase and try to implement them. Don't be shy to update your plans if you find things easier/harder than you thought. The earlier you revise problems, the easier they will be to fix.
|
||||
|
||||
A good idea is to host your code online (publicly or privately) using version control. Not only will this make it easy for multiple coders to collaborate (and have a bug-tracker etc), it also means your work is backed up at all times. The [Version Control](Version-Control) tutorial has instructions for setting up a sane developer environment with proper version control.
|
||||
A good idea is to host your code online (publicly or privately) using version control. Not only will this make it easy for multiple coders to collaborate (and have a bug-tracker etc), it also means your work is backed up at all times. The [Version Control](./Version-Control) tutorial has instructions for setting up a sane developer environment with proper version control.
|
||||
|
||||
### "Tech Demo" Building
|
||||
|
||||
|
|
@ -102,7 +102,7 @@ During building you get free and extensive testing of whatever custom build comm
|
|||
|
||||
## Alpha Release
|
||||
|
||||
As mentioned, don't hold onto your world more than necessary. *Get it out there* with a huge *Alpha* flag and let people try it! Call upon your alpha-players to try everything - they *will* find ways to break your game in ways that you never could have imagined. In Alpha you might be best off to focus on inviting friends and maybe other MUD developers, people who you can pester to give proper feedback and bug reports (there *will* be bugs, there is no way around it). Follow the quick instructions for [Online Setup](Online-Setup) to make your game visible online. If you hadn't already, make sure to put up your game on the [Evennia game index](http://games.evennia.com/) so people know it's in the works (actually, even pre-alpha games are allowed in the index so don't be shy)!
|
||||
As mentioned, don't hold onto your world more than necessary. *Get it out there* with a huge *Alpha* flag and let people try it! Call upon your alpha-players to try everything - they *will* find ways to break your game in ways that you never could have imagined. In Alpha you might be best off to focus on inviting friends and maybe other MUD developers, people who you can pester to give proper feedback and bug reports (there *will* be bugs, there is no way around it). Follow the quick instructions for [Online Setup](./Online-Setup) to make your game visible online. If you hadn't already, make sure to put up your game on the [Evennia game index](http://games.evennia.com/) so people know it's in the works (actually, even pre-alpha games are allowed in the index so don't be shy)!
|
||||
|
||||
## Beta Release/Perpetual Beta
|
||||
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ The line that is most relevant here is the game time epoch. You see it shown at
|
|||
|
||||
The `gametime` utility also has a way to schedule game-related events, taking into account your game time, and assuming a standard calendar (see below for the same feature with a custom calendar). For instance, it can be used to have a specific message every (in-game) day at 6:00 AM showing how the sun rises.
|
||||
|
||||
The function `schedule()` should be used here. It will create a [script](Scripts) with some additional features to make sure the script is always executed when the game time matches the given parameters.
|
||||
The function `schedule()` should be used here. It will create a [script](./Scripts) with some additional features to make sure the script is always executed when the game time matches the given parameters.
|
||||
|
||||
The `schedule` function takes the following arguments:
|
||||
|
||||
|
|
|
|||
|
|
@ -7,15 +7,15 @@ This will help you download, install and start Evennia for the first time.
|
|||
> test out Evennia. Apart from downloading and updating you don't even need an
|
||||
> internet connection until you feel ready to share your game with the world.
|
||||
|
||||
- [Quick Start](Getting-Started#quick-start)
|
||||
- [Requirements](Getting-Started#requirements)
|
||||
- [Linux Install](Getting-Started#linux-install)
|
||||
- [Mac Install](Getting-Started#mac-install)
|
||||
- [Windows Install](Getting-Started#windows-install)
|
||||
- [Running in Docker](Running-Evennia-in-Docker)
|
||||
- [Where to Go Next](Getting-Started#where-to-go-next)
|
||||
- [Troubleshooting](Getting-Started#troubleshooting)
|
||||
- [Glossary of terms](Glossary)
|
||||
- [Quick Start](./Getting-Started#quick-start)
|
||||
- [Requirements](./Getting-Started#requirements)
|
||||
- [Linux Install](./Getting-Started#linux-install)
|
||||
- [Mac Install](./Getting-Started#mac-install)
|
||||
- [Windows Install](./Getting-Started#windows-install)
|
||||
- [Running in Docker](./Running-Evennia-in-Docker)
|
||||
- [Where to Go Next](./Getting-Started#where-to-go-next)
|
||||
- [Troubleshooting](./Getting-Started#troubleshooting)
|
||||
- [Glossary of terms](./Glossary)
|
||||
|
||||
## Quick Start
|
||||
|
||||
|
|
@ -35,7 +35,7 @@ more detailed instructions for your platform.
|
|||
10. `evennia start` (make sure to make a superuser when asked)
|
||||
Evennia should now be running and you can connect to it by pointing a web browser to `http://localhost:4001` or a MUD telnet client to `localhost:4000` (use `127.0.0.1` if your OS does not recognize `localhost`).
|
||||
|
||||
We also release [Docker images](Running-Evennia-in-Docker)
|
||||
We also release [Docker images](./Running-Evennia-in-Docker)
|
||||
based on `master` and `develop` branches.
|
||||
|
||||
## Requirements
|
||||
|
|
@ -64,10 +64,10 @@ updating Evennia itself - Mac users can use the
|
|||
## Linux Install
|
||||
|
||||
If you run into any issues during the installation and first start, please
|
||||
check out [Linux Troubleshooting](Getting-Started#linux-troubleshooting).
|
||||
check out [Linux Troubleshooting](./Getting-Started#linux-troubleshooting).
|
||||
|
||||
For Debian-derived systems (like Ubuntu, Mint etc), start a terminal and
|
||||
install the [dependencies](Getting-Started#requirements):
|
||||
install the [dependencies](./Getting-Started#requirements):
|
||||
|
||||
```
|
||||
sudo apt-get update
|
||||
|
|
@ -136,8 +136,8 @@ folders) and run
|
|||
pip install -e evennia
|
||||
```
|
||||
|
||||
For more info about `pip`, see the [Glossary entry on pip](Glossary#pip). If
|
||||
install failed with any issues, see [Linux Troubleshooting](Getting-Started#linux-troubleshooting).
|
||||
For more info about `pip`, see the [Glossary entry on pip](./Glossary#pip). If
|
||||
install failed with any issues, see [Linux Troubleshooting](./Getting-Started#linux-troubleshooting).
|
||||
|
||||
Next we'll start our new game, here called "mygame". This will create yet
|
||||
another new folder where you will be creating your new game:
|
||||
|
|
@ -154,8 +154,8 @@ Your final folder structure should look like this:
|
|||
mygame/
|
||||
```
|
||||
|
||||
You can [configure Evennia](Server-Conf#settings-file) extensively, for example
|
||||
to use a [different database](Choosing-An-SQL-Server). For now we'll just stick
|
||||
You can [configure Evennia](./Server-Conf#settings-file) extensively, for example
|
||||
to use a [different database](./Choosing-An-SQL-Server). For now we'll just stick
|
||||
to the defaults though.
|
||||
|
||||
```
|
||||
|
|
@ -169,7 +169,7 @@ evennia start # (create a superuser when asked. Email is optional.)
|
|||
|
||||
Your game should now be running! Open a web browser at `http://localhost:4001`
|
||||
or point a telnet client to `localhost:4000` and log in with the user you
|
||||
created. Check out [where to go next](Getting-Started#where-to-go-next).
|
||||
created. Check out [where to go next](./Getting-Started#where-to-go-next).
|
||||
|
||||
|
||||
## Mac Install
|
||||
|
|
@ -177,7 +177,7 @@ created. Check out [where to go next](Getting-Started#where-to-go-next).
|
|||
The Evennia server is a terminal program. Open the terminal e.g. from
|
||||
*Applications->Utilities->Terminal*. [Here is an introduction to the Mac terminal](http://blog.teamtreehouse.com/introduction-to-the-mac-os-x-command-line)
|
||||
if you are unsure how it works. If you run into any issues during the
|
||||
installation, please check out [Mac Troubleshooting](Getting-Started#mac-troubleshooting).
|
||||
installation, please check out [Mac Troubleshooting](./Getting-Started#mac-troubleshooting).
|
||||
|
||||
* Python should already be installed but you must make sure it's a high enough version.
|
||||
([This](http://docs.python-guide.org/en/latest/starting/install/osx/) discusses
|
||||
|
|
@ -208,7 +208,7 @@ A new folder `evennia` will appear containing the Evennia library. This only
|
|||
contains the source code though, it is not *installed* yet. To isolate the
|
||||
Evennia install and its dependencies from the rest of the system, it is good
|
||||
Python practice to install into a _virtualenv_. If you are unsure about what a
|
||||
virtualenv is and why it's useful, see the [Glossary entry on virtualenv](Glossary#virtualenv).
|
||||
virtualenv is and why it's useful, see the [Glossary entry on virtualenv](./Glossary#virtualenv).
|
||||
|
||||
Run `python -V` to check which Python your system defaults to.
|
||||
|
||||
|
|
@ -246,8 +246,8 @@ pip install --upgrade setuptools # Ditto concerning Mac issues.
|
|||
pip install -e evennia
|
||||
```
|
||||
|
||||
For more info about `pip`, see the [Glossary entry on pip](Glossary#pip). If
|
||||
install failed with any issues, see [Mac Troubleshooting](Getting-Started#mac-troubleshooting).
|
||||
For more info about `pip`, see the [Glossary entry on pip](./Glossary#pip). If
|
||||
install failed with any issues, see [Mac Troubleshooting](./Getting-Started#mac-troubleshooting).
|
||||
|
||||
Next we'll start our new game. We'll call it "mygame" here. This creates a new
|
||||
folder where you will be creating your new game:
|
||||
|
|
@ -265,8 +265,8 @@ Your final folder structure should look like this:
|
|||
mygame/
|
||||
```
|
||||
|
||||
You can [configure Evennia](Server-Conf#settings-file) extensively, for example
|
||||
to use a [different database](Choosing-An-SQL-Server). We'll go with the
|
||||
You can [configure Evennia](./Server-Conf#settings-file) extensively, for example
|
||||
to use a [different database](./Choosing-An-SQL-Server). We'll go with the
|
||||
defaults here.
|
||||
|
||||
```
|
||||
|
|
@ -280,13 +280,13 @@ evennia start # (create a superuser when asked. Email is optional.)
|
|||
|
||||
Your game should now be running! Open a web browser at `http://localhost:4001`
|
||||
or point a telnet client to `localhost:4000` and log in with the user you
|
||||
created. Check out [where to go next](Getting-Started#where-to-go-next).
|
||||
created. Check out [where to go next](./Getting-Started#where-to-go-next).
|
||||
|
||||
|
||||
## Windows Install
|
||||
|
||||
If you run into any issues during the installation, please check out
|
||||
[Windows Troubleshooting](Getting-Started#windows-troubleshooting).
|
||||
[Windows Troubleshooting](./Getting-Started#windows-troubleshooting).
|
||||
|
||||
> If you are running Windows10, consider using the Windows Subsystem for Linux
|
||||
> ([WSL](https://en.wikipedia.org/wiki/Windows_Subsystem_for_Linux)) instead.
|
||||
|
|
@ -335,7 +335,7 @@ A new folder `evennia` will appear containing the Evennia library. This only
|
|||
contains the source code though, it is not *installed* yet. To isolate the
|
||||
Evennia install and its dependencies from the rest of the system, it is good
|
||||
Python practice to install into a _virtualenv_. If you are unsure about what a
|
||||
virtualenv is and why it's useful, see the [Glossary entry on virtualenv](Glossary#virtualenv).
|
||||
virtualenv is and why it's useful, see the [Glossary entry on virtualenv](./Glossary#virtualenv).
|
||||
|
||||
In your console, try `python -V` to see which version of Python your system
|
||||
defaults to.
|
||||
|
|
@ -380,8 +380,8 @@ folders when you use the `dir` command) and run
|
|||
```
|
||||
pip install -e evennia
|
||||
```
|
||||
For more info about `pip`, see the [Glossary entry on pip](Glossary#pip). If
|
||||
the install failed with any issues, see [Windows Troubleshooting](Getting-Started#windows-troubleshooting).
|
||||
For more info about `pip`, see the [Glossary entry on pip](./Glossary#pip). If
|
||||
the install failed with any issues, see [Windows Troubleshooting](./Getting-Started#windows-troubleshooting).
|
||||
Next we'll start our new game, we'll call it "mygame" here. This creates a new folder where you will be
|
||||
creating your new game:
|
||||
|
||||
|
|
@ -398,8 +398,8 @@ path\to\muddev
|
|||
mygame\
|
||||
```
|
||||
|
||||
You can [configure Evennia](Server-Conf#settings-file) extensively, for example
|
||||
to use a [different database](Choosing-An-SQL-Server). We'll go with the
|
||||
You can [configure Evennia](./Server-Conf#settings-file) extensively, for example
|
||||
to use a [different database](./Choosing-An-SQL-Server). We'll go with the
|
||||
defaults here.
|
||||
|
||||
```
|
||||
|
|
@ -413,7 +413,7 @@ evennia start # (create a superuser when asked. Email is optional.)
|
|||
|
||||
Your game should now be running! Open a web browser at `http://localhost:4001`
|
||||
or point a telnet client to `localhost:4000` and log in with the user you
|
||||
created. Check out [where to go next](Getting-Started#where-to-go-next).
|
||||
created. Check out [where to go next](./Getting-Started#where-to-go-next).
|
||||
|
||||
|
||||
## Where to Go Next
|
||||
|
|
@ -423,16 +423,16 @@ logged in, stand in the `Limbo` room and run
|
|||
|
||||
@batchcommand tutorial_world.build
|
||||
|
||||
to build [Evennia's tutorial world](Tutorial-World-Introduction) - it's a small solo quest to explore. Only run the instructed `@batchcommand` once. You'll get a lot of text scrolling by as the tutorial is built. Once done, the `tutorial` exit will have appeared out of Limbo - just write `tutorial` to enter it.
|
||||
to build [Evennia's tutorial world](./Tutorial-World-Introduction) - it's a small solo quest to explore. Only run the instructed `@batchcommand` once. You'll get a lot of text scrolling by as the tutorial is built. Once done, the `tutorial` exit will have appeared out of Limbo - just write `tutorial` to enter it.
|
||||
|
||||
Once you get back to `Limbo` from the tutorial (if you get stuck in the tutorial quest you can do `@tel #2` to jump to Limbo), a good idea is to learn how to [start, stop and reload](Start-Stop-Reload) the Evennia server. You may also want to familiarize yourself with some [commonly used terms in our Glossary](Glossary). After that, why not experiment with [creating some new items and build some new rooms](Building-Quickstart) out from Limbo.
|
||||
Once you get back to `Limbo` from the tutorial (if you get stuck in the tutorial quest you can do `@tel #2` to jump to Limbo), a good idea is to learn how to [start, stop and reload](./Start-Stop-Reload) the Evennia server. You may also want to familiarize yourself with some [commonly used terms in our Glossary](./Glossary). After that, why not experiment with [creating some new items and build some new rooms](./Building-Quickstart) out from Limbo.
|
||||
|
||||
From here on, you could move on to do one of our [introductory tutorials](Tutorials) or simply dive headlong into Evennia's comprehensive [manual](https://github.com/evennia/evennia/wiki). While Evennia has no major game systems out of the box, we do supply a range of optional *contribs* that you can use or borrow from. They range from dice rolling and alternative color schemes to barter and combat systems. You can find the [growing list of contribs here](https://github.com/evennia/evennia/blob/master/evennia/contrib/README.md).
|
||||
From here on, you could move on to do one of our [introductory tutorials](./Tutorials) or simply dive headlong into Evennia's comprehensive [manual](https://github.com/evennia/evennia/wiki). While Evennia has no major game systems out of the box, we do supply a range of optional *contribs* that you can use or borrow from. They range from dice rolling and alternative color schemes to barter and combat systems. You can find the [growing list of contribs here](https://github.com/evennia/evennia/blob/master/evennia/contrib/README.md).
|
||||
|
||||
If you have any questions, you can always ask in [the developer chat](http://webchat.freenode.net/?channels=evennia&uio=MT1mYWxzZSY5PXRydWUmMTE9MTk1JjEyPXRydWUbb) `#evennia` on `irc.freenode.net` or by posting to the [Evennia forums](https://groups.google.com/forum/#%21forum/evennia). You can also join the [Discord Server](https://discord.gg/NecFePw).
|
||||
|
||||
Finally, if you are itching to help out or support Evennia (awesome!) have an
|
||||
issue to report or a feature to request, [see here](How-To-Get-And-Give-Help).
|
||||
issue to report or a feature to request, [see here](./How-To-Get-And-Give-Help).
|
||||
|
||||
Enjoy your stay!
|
||||
|
||||
|
|
|
|||
|
|
@ -3,89 +3,89 @@
|
|||
|
||||
This explains common recurring terms used in the Evennia docs. It will be expanded as needed.
|
||||
|
||||
- _[account](Glossary#account)_ - the player's account on the game
|
||||
- _[admin-site](Glossary#admin-site)_ - the Django web page for manipulating the database
|
||||
- _[attribute](Glossary#attribute)_ - persistent, custom data stored on typeclasses
|
||||
- _[channel](Glossary#channel)_ - game communication channels
|
||||
- _[character](Glossary#character)_ - the player's avatar in the game, controlled from _[account](Glossary#account)_
|
||||
- _[core](Glossary#core)_ - a term used for the code distributed with Evennia proper
|
||||
- _[django](Glossary#django)_ - web framework Evennia uses for database access and web integration
|
||||
- _[field](Glossary#field)_ - a _[typeclass](Glossary#typeclass)_ property representing a database column
|
||||
- _[git](Glossary#git)_ - the version-control system we use
|
||||
- _[github](Glossary#github)_ - the online hosting of our source code
|
||||
- _[migrate](Glossary#migrate)_ - updating the database schema
|
||||
- _[account](./Glossary#account)_ - the player's account on the game
|
||||
- _[admin-site](./Glossary#admin-site)_ - the Django web page for manipulating the database
|
||||
- _[attribute](./Glossary#attribute)_ - persistent, custom data stored on typeclasses
|
||||
- _[channel](./Glossary#channel)_ - game communication channels
|
||||
- _[character](./Glossary#character)_ - the player's avatar in the game, controlled from _[account](./Glossary#account)_
|
||||
- _[core](./Glossary#core)_ - a term used for the code distributed with Evennia proper
|
||||
- _[django](./Glossary#django)_ - web framework Evennia uses for database access and web integration
|
||||
- _[field](./Glossary#field)_ - a _[typeclass](./Glossary#typeclass)_ property representing a database column
|
||||
- _[git](./Glossary#git)_ - the version-control system we use
|
||||
- _[github](./Glossary#github)_ - the online hosting of our source code
|
||||
- _[migrate](./Glossary#migrate)_ - updating the database schema
|
||||
- _[multisession mode`](#multisession-mode)_ - a setting defining how users connect to Evennia
|
||||
- _[object](Glossary#object)_ - Python instance, general term or in-game _[typeclass](Glossary#typeclass)_
|
||||
- _[pip](Glossary#pip)_ - the Python installer
|
||||
- _[object](./Glossary#object)_ - Python instance, general term or in-game _[typeclass](./Glossary#typeclass)_
|
||||
- _[pip](./Glossary#pip)_ - the Python installer
|
||||
- _player_ - the human connecting to the game with their client
|
||||
- _[puppet](Glossary#puppet)_ - when an [account](Glossary#account) controls an in-game [object](Glossary#object)
|
||||
- _[property](Glossary#property)_ - a python property
|
||||
- _evenv_ - see _[virtualenv](Glossary#virtualenv)_
|
||||
- _[repository](Glossary#repository)_ - a store of source code + source history
|
||||
- _[script](Glossary#script)_ - a building block for custom storage, systems and time-keepint
|
||||
- _[session](Glossary#session)_ - represents one client connection
|
||||
- _[ticker](Glossary#ticker)_ - Allows to run events on a steady 'tick'
|
||||
- _[twisted](Glossary#twisted)_ - networking engine responsible for Evennia's event loop and communications
|
||||
- _[typeclass](Glossary#typeclass)_ - Evennia's database-connected Python class
|
||||
- _upstream_ - see _[github](Glossary#github)_
|
||||
- _[virtualenv](Glossary#virtualenv)_ - a Python program and way to make an isolated Python install
|
||||
- _[puppet](./Glossary#puppet)_ - when an [account](./Glossary#account) controls an in-game [object](./Glossary#object)
|
||||
- _[property](./Glossary#property)_ - a python property
|
||||
- _evenv_ - see _[virtualenv](./Glossary#virtualenv)_
|
||||
- _[repository](./Glossary#repository)_ - a store of source code + source history
|
||||
- _[script](./Glossary#script)_ - a building block for custom storage, systems and time-keepint
|
||||
- _[session](./Glossary#session)_ - represents one client connection
|
||||
- _[ticker](./Glossary#ticker)_ - Allows to run events on a steady 'tick'
|
||||
- _[twisted](./Glossary#twisted)_ - networking engine responsible for Evennia's event loop and communications
|
||||
- _[typeclass](./Glossary#typeclass)_ - Evennia's database-connected Python class
|
||||
- _upstream_ - see _[github](./Glossary#github)_
|
||||
- _[virtualenv](./Glossary#virtualenv)_ - a Python program and way to make an isolated Python install
|
||||
|
||||
|
||||
---
|
||||
|
||||
### _account_
|
||||
|
||||
The term 'account' refers to the [player's](Glossary#player) unique account on the game. It is represented by the `Account` [typeclass](Glossary#typeclass) and holds things like email, password, configuration etc.
|
||||
The term 'account' refers to the [player's](./Glossary#player) unique account on the game. It is represented by the `Account` [typeclass](./Glossary#typeclass) and holds things like email, password, configuration etc.
|
||||
|
||||
When a player connects to the game, they connect to their account. The account has *no* representation in the game world. Through their Account they can instead choose to [puppet](Glossary#puppet) one (or more, depending on game mode) [Characters](Glossary#character) in the game.
|
||||
When a player connects to the game, they connect to their account. The account has *no* representation in the game world. Through their Account they can instead choose to [puppet](./Glossary#puppet) one (or more, depending on game mode) [Characters](./Glossary#character) in the game.
|
||||
|
||||
In the default [multisession mode](Sessions#multisession-mode) of Evennia, you immediately start puppeting a Character with the same name as your Account when you log in - mimicking how older servers used to work.
|
||||
In the default [multisession mode](./Sessions#multisession-mode) of Evennia, you immediately start puppeting a Character with the same name as your Account when you log in - mimicking how older servers used to work.
|
||||
|
||||
### _admin-site_
|
||||
|
||||
This usually refers to [Django's](Glossary#django) *Admin site* or database-administration web page ([link to Django docs](https://docs.djangoproject.com/en/2.1/ref/contrib/admin/)). The admin site is an automatically generated web interface to the database (it can be customized extensively). It's reachable from the `admin` link on the default Evennia website you get with your server.
|
||||
This usually refers to [Django's](./Glossary#django) *Admin site* or database-administration web page ([link to Django docs](https://docs.djangoproject.com/en/2.1/ref/contrib/admin/)). The admin site is an automatically generated web interface to the database (it can be customized extensively). It's reachable from the `admin` link on the default Evennia website you get with your server.
|
||||
|
||||
### _attribute_
|
||||
|
||||
The term _Attribute_ should not be confused with ([properties](Glossary#property) or [fields](Glossary#field). The `Attribute` represents arbitrary pieces of data that can be attached to any [typeclassed](Glossary#typeclass) entity in Evennia. Attributes allows storing new persistent data on typeclasses without changing their underlying database schemas. [Read more about Attributes here](Attributes).
|
||||
The term _Attribute_ should not be confused with ([properties](./Glossary#property) or [fields](./Glossary#field). The `Attribute` represents arbitrary pieces of data that can be attached to any [typeclassed](./Glossary#typeclass) entity in Evennia. Attributes allows storing new persistent data on typeclasses without changing their underlying database schemas. [Read more about Attributes here](./Attributes).
|
||||
|
||||
### _channel_
|
||||
|
||||
A _Channel_ refers to an in-game communication channel. It's an entity that people subscribe to and which re-distributes messages between all subscribers. Such subscribers default to being [Accounts](Glossary#account), for out-of-game communication but could also be [Objects (usually Characters)](Glossary#character) if one wanted to adopt Channels for things like in-game walkie-talkies or phone systems. It is represented by the `Channel` typeclass. [You can read more about the comm system here](Communications#channels).
|
||||
A _Channel_ refers to an in-game communication channel. It's an entity that people subscribe to and which re-distributes messages between all subscribers. Such subscribers default to being [Accounts](./Glossary#account), for out-of-game communication but could also be [Objects (usually Characters)](./Glossary#character) if one wanted to adopt Channels for things like in-game walkie-talkies or phone systems. It is represented by the `Channel` typeclass. [You can read more about the comm system here](./Communications#channels).
|
||||
|
||||
### _character_
|
||||
|
||||
The _Character_ is the term we use for the default avatar being [puppeted](Glossary#puppet) by the [account](Glossary#account) in the game world. It is represented by the `Character` typeclass (which is a child of [Object](Glossary#object)). Many developers use children of this class to represent monsters and other NPCs. You can [read more about it here](Objects#subclasses-of-object).
|
||||
The _Character_ is the term we use for the default avatar being [puppeted](./Glossary#puppet) by the [account](./Glossary#account) in the game world. It is represented by the `Character` typeclass (which is a child of [Object](./Glossary#object)). Many developers use children of this class to represent monsters and other NPCs. You can [read more about it here](./Objects#subclasses-of-object).
|
||||
|
||||
### _django_
|
||||
|
||||
[Django](https://www.djangoproject.com/) is a professional and very popular Python web framework, similar to Rails for the Ruby language. It is one of Evennia's central library dependencies (the other one is [Twisted](Glossary#twisted)). Evennia uses Django for two main things - to map all database operations to Python and for structuring our web site.
|
||||
[Django](https://www.djangoproject.com/) is a professional and very popular Python web framework, similar to Rails for the Ruby language. It is one of Evennia's central library dependencies (the other one is [Twisted](./Glossary#twisted)). Evennia uses Django for two main things - to map all database operations to Python and for structuring our web site.
|
||||
|
||||
Through Django, we can work with any supported database (SQlite3, Postgres, MySQL ...) using generic Python instead of database-specific SQL: A database table is represented in Django as a Python class (called a *model*). An Python instance of such a class represents a row in that table.
|
||||
|
||||
There is usually no need to know the details of Django's database handling in order to use Evennia - it will handle most of the complexity for you under the hood using what we call [typeclasses](Glossary#typeclass). But should you need the power of Django you can always get it. Most commonly people want to use "raw" Django when doing more advanced/custom database queries than offered by Evennia's [default search functions](Tutorial-Searching-For-Objects). One will then need to read about Django's _querysets_. Querysets are Python method calls on a special form that lets you build complex queries. They get converted into optimized SQL queries under the hood, suitable for your current database. [Here is our tutorial/explanation of Django queries](Tutorial-Searching-For-Objects#queries-in-django).
|
||||
There is usually no need to know the details of Django's database handling in order to use Evennia - it will handle most of the complexity for you under the hood using what we call [typeclasses](./Glossary#typeclass). But should you need the power of Django you can always get it. Most commonly people want to use "raw" Django when doing more advanced/custom database queries than offered by Evennia's [default search functions](./Tutorial-Searching-For-Objects). One will then need to read about Django's _querysets_. Querysets are Python method calls on a special form that lets you build complex queries. They get converted into optimized SQL queries under the hood, suitable for your current database. [Here is our tutorial/explanation of Django queries](./Tutorial-Searching-For-Objects#queries-in-django).
|
||||
|
||||
> By the way, Django (and Evennia) does allow you to fall through and send raw SQL if you really want to. It's highly unlikely to be needed though; the Django database abstraction is very, very powerful.
|
||||
|
||||
The other aspect where Evennia uses Django is for web integration. On one end Django gives an infrastructure for wiring Python functions (called *views*) to URLs: the view/function is called when a user goes that URL in their browser, enters data into a form etc. The return is the web page to show. Django also offers templating with features such as being able to add special markers in HTML where it will insert the values of Python variables on the fly (like showing the current player count on the web page). [Here is one of our tutorials on wiring up such a web page](Add-a-simple-new-web-page). Django also comes with the [admin site](Glossary#admin-site), which automatically maps the database into a form accessible from a web browser.
|
||||
The other aspect where Evennia uses Django is for web integration. On one end Django gives an infrastructure for wiring Python functions (called *views*) to URLs: the view/function is called when a user goes that URL in their browser, enters data into a form etc. The return is the web page to show. Django also offers templating with features such as being able to add special markers in HTML where it will insert the values of Python variables on the fly (like showing the current player count on the web page). [Here is one of our tutorials on wiring up such a web page](./Add-a-simple-new-web-page). Django also comes with the [admin site](./Glossary#admin-site), which automatically maps the database into a form accessible from a web browser.
|
||||
|
||||
### _core_
|
||||
|
||||
This term is sometimes used to represent the main Evennia library code suite, *excluding* its [contrib](Glossary#contrib) directory. It can sometimes come up in code reviews, such as
|
||||
This term is sometimes used to represent the main Evennia library code suite, *excluding* its [contrib](./Glossary#contrib) directory. It can sometimes come up in code reviews, such as
|
||||
|
||||
> Evennia is game-agnostic but this feature is for a particular game genre. So it does not belong in core. Better make it a contrib.
|
||||
|
||||
### _field_
|
||||
|
||||
A _field_ or _database field_ in Evennia refers to a [property](Glossary#property) on a [typeclass](Glossary#typeclass) directly linked to an underlying database column. Only a few fixed properties per typeclass are database fields but they are often tied to the core functionality of that base typeclass (for example [Objects](Glossary#object) store its location as a field). In all other cases, [attributes](Glossary#attribute) are used to add new persistent data to the typeclass. [Read more about typeclass properties here](Typeclasses#about-typeclass-properties).
|
||||
A _field_ or _database field_ in Evennia refers to a [property](./Glossary#property) on a [typeclass](./Glossary#typeclass) directly linked to an underlying database column. Only a few fixed properties per typeclass are database fields but they are often tied to the core functionality of that base typeclass (for example [Objects](./Glossary#object) store its location as a field). In all other cases, [attributes](./Glossary#attribute) are used to add new persistent data to the typeclass. [Read more about typeclass properties here](./Typeclasses#about-typeclass-properties).
|
||||
|
||||
### _git_
|
||||
|
||||
[Git](https://git-scm.com/) is a [version control](https://en.wikipedia.org/wiki/Version_control) tool. It allows us to track the development of the Evennia code by dividing it into units called *commits*. A 'commit' is sort of a save-spot - you save the current state of your code and can then come back to it later if later changes caused problems. By tracking commits we know what 'version' of the code we are currently using.
|
||||
|
||||
Evennia's source code + its source history is jointly called a [repository](Glossary#repository). This is centrally stored at our online home on [GitHub](Glossary#github). Everyone using or developing Evennia makes a 'clone' of this repository to their own computer - everyone automatically gets everything that is online, including all the code history.
|
||||
Evennia's source code + its source history is jointly called a [repository](./Glossary#repository). This is centrally stored at our online home on [GitHub](./Glossary#github). Everyone using or developing Evennia makes a 'clone' of this repository to their own computer - everyone automatically gets everything that is online, including all the code history.
|
||||
|
||||
> Don't confuse Git and [GitHub](Glossary#github). The former is the version control system. The latter is a website (run by a company) that allows you to upload source code controlled by Git for others to see (among other things).
|
||||
> Don't confuse Git and [GitHub](./Glossary#github). The former is the version control system. The latter is a website (run by a company) that allows you to upload source code controlled by Git for others to see (among other things).
|
||||
|
||||
Git allows multiple users from around the world to efficiently collaborate on Evennia's code: People can make local commits on their cloned code. The commits they do can then be uploaded to GitHub and reviewed by the Evennia lead devs - and if the changes look ok they can be safely *merged* into the central Evennia code - and everyone can *pull* those changes to update their local copies.
|
||||
|
||||
|
|
@ -95,33 +95,33 @@ Common usage (for non-Evennia developers):
|
|||
- `git clone <github-url>` - clone an online repository to your computer. This is what you do when you 'download' Evennia. You only need to do this once.
|
||||
- `git pull` (inside local copy of repository) - sync your local repository with what is online.
|
||||
|
||||
> Full usage of Git is way beyond the scope of this glossary. See [Tutorial - version control](Version-Control) for more info and links to the Git documentation.
|
||||
> Full usage of Git is way beyond the scope of this glossary. See [Tutorial - version control](./Version-Control) for more info and links to the Git documentation.
|
||||
|
||||
### _migrate_
|
||||
|
||||
This term is used for upgrading the database structure (it's _schema_ )to a new version. Most often this is due to Evennia's [upstream](Glossary#github) schema changing. When that happens you need to migrate that schema to the new version as well. Once you have used [git](Glossary#git) to pull the latest changes, just `cd` into your game dir and run
|
||||
This term is used for upgrading the database structure (it's _schema_ )to a new version. Most often this is due to Evennia's [upstream](./Glossary#github) schema changing. When that happens you need to migrate that schema to the new version as well. Once you have used [git](./Glossary#git) to pull the latest changes, just `cd` into your game dir and run
|
||||
|
||||
evennia migrate
|
||||
|
||||
That should be it (see [virtualenv](Glossary#virtualenv) if you get a warning that the `evennia` command is not available). See also [Updating your game](Updating-Your-Game) for more details.
|
||||
That should be it (see [virtualenv](./Glossary#virtualenv) if you get a warning that the `evennia` command is not available). See also [Updating your game](./Updating-Your-Game) for more details.
|
||||
|
||||
> Technically, migrations are shipped as little Python snippets of code that explains which database actions must be taken to upgrade from one version of the schema to the next. When you run the command above, those snippets are run in sequence.
|
||||
|
||||
### _multisession mode_
|
||||
|
||||
This term refers to the `MULTISESSION_MODE` setting, which has a value of 0 to 3. The mode alters how players can connect to the game, such as how many Sessions a player can start with one account and how many Characters they can control at the same time. It is [described in detail here](Sessions#multisession-mode).
|
||||
This term refers to the `MULTISESSION_MODE` setting, which has a value of 0 to 3. The mode alters how players can connect to the game, such as how many Sessions a player can start with one account and how many Characters they can control at the same time. It is [described in detail here](./Sessions#multisession-mode).
|
||||
|
||||
### _github_
|
||||
|
||||
[Github](https://github.com/evennia) is where Evennia's source code and documentation is hosted. This online [repository](Glossary#repository) of code we also sometimes refer to as _upstream_.
|
||||
[Github](https://github.com/evennia) is where Evennia's source code and documentation is hosted. This online [repository](./Glossary#repository) of code we also sometimes refer to as _upstream_.
|
||||
|
||||
GitHub is a business, offering free hosting to Open-source projects like Evennia. Despite the similarity in name, don't confuse GitHub the website with [Git](Glossary#git), the versioning system. Github hosts Git [repositories](Glossary#repository) online and helps with collaboration and infrastructure. Git itself is a separate project.
|
||||
GitHub is a business, offering free hosting to Open-source projects like Evennia. Despite the similarity in name, don't confuse GitHub the website with [Git](./Glossary#git), the versioning system. Github hosts Git [repositories](./Glossary#repository) online and helps with collaboration and infrastructure. Git itself is a separate project.
|
||||
|
||||
### _object_
|
||||
|
||||
In general Python (and other [object-oriented languages](https://en.wikipedia.org/wiki/Object-oriented_programming)), an `object` is what we call the instance of a *class*. But one of Evennia's core [typeclasses](Glossary#typeclasss) is also called "Object". To separate these in the docs we try to use `object` to refer to the general term and capitalized `Object` when we refer to the typeclass.
|
||||
In general Python (and other [object-oriented languages](https://en.wikipedia.org/wiki/Object-oriented_programming)), an `object` is what we call the instance of a *class*. But one of Evennia's core [typeclasses](./Glossary#typeclasss) is also called "Object". To separate these in the docs we try to use `object` to refer to the general term and capitalized `Object` when we refer to the typeclass.
|
||||
|
||||
The `Object` is a typeclass that represents all *in-game* entities, including [Characters](Glossary#character), rooms, trees, weapons etc. [Read more about Objects here](Objects).
|
||||
The `Object` is a typeclass that represents all *in-game* entities, including [Characters](./Glossary#character), rooms, trees, weapons etc. [Read more about Objects here](./Objects).
|
||||
|
||||
### _pip_
|
||||
|
||||
|
|
@ -135,49 +135,49 @@ Common usage:
|
|||
- `pip install <folder>` - install a Python package you have downloaded earlier (or cloned using git).
|
||||
- `pip install -e <folder>` - install a local package by just making a soft link to the folder. This means that if the code in `<folder>` changes, the installed Python package is immediately updated. If not using `-e`, one would need to run `pip install --upgrade <folder>` every time to make the changes available when you import this package into your code. Evennia is installed this way.
|
||||
|
||||
For development, `pip` is usually used together with a [virtualenv](Glossary#virtualenv) to install all packages and dependencies needed for a project in one, isolated location on the hard drive.
|
||||
For development, `pip` is usually used together with a [virtualenv](./Glossary#virtualenv) to install all packages and dependencies needed for a project in one, isolated location on the hard drive.
|
||||
|
||||
### _puppet_
|
||||
|
||||
An [account](Glossary#account) can take control and "play as" any [Object](Glossary#object). When doing so, we call this _puppeting_, (like [puppeteering](https://en.wikipedia.org/wiki/Puppeteer)). Normally the entity being puppeted is of the [Character](Glossary#character) subclass but it does not have to be.
|
||||
An [account](./Glossary#account) can take control and "play as" any [Object](./Glossary#object). When doing so, we call this _puppeting_, (like [puppeteering](https://en.wikipedia.org/wiki/Puppeteer)). Normally the entity being puppeted is of the [Character](./Glossary#character) subclass but it does not have to be.
|
||||
|
||||
### _property_
|
||||
|
||||
A _property_ is a general term used for properties on any Python object. The term also sometimes refers to the `property` built-in function of Python ([read more here](https://www.python-course.eu/python3_properties.php)). Note the distinction between properties, [fields](Glossary#field) and [Attributes](Glossary#attribute).
|
||||
A _property_ is a general term used for properties on any Python object. The term also sometimes refers to the `property` built-in function of Python ([read more here](https://www.python-course.eu/python3_properties.php)). Note the distinction between properties, [fields](./Glossary#field) and [Attributes](./Glossary#attribute).
|
||||
|
||||
### _repository_
|
||||
|
||||
A _repository_ is a version control/[git](Glossary#git) term. It represents a folder containing source code plus its versioning history.
|
||||
A _repository_ is a version control/[git](./Glossary#git) term. It represents a folder containing source code plus its versioning history.
|
||||
|
||||
> In Git's case, that history is stored in a hidden folder `.git`. If you ever feel the need to look into this folder you probably already know enough Git to know why.
|
||||
|
||||
The `evennia` folder you download from us with `git clone` is a repository. The code on [GitHub](Glossary#github) is often referred to as the 'online repository' (or the _upstream_ repository). If you put your game dir under version control, that of course becomes a repository as well.
|
||||
The `evennia` folder you download from us with `git clone` is a repository. The code on [GitHub](./Glossary#github) is often referred to as the 'online repository' (or the _upstream_ repository). If you put your game dir under version control, that of course becomes a repository as well.
|
||||
|
||||
### _script_
|
||||
|
||||
When we refer to _Scripts_, we generally refer to the `Script` [typeclass](Typeclasses). Scripts are the mavericks of Evennia - they are like [Objects](Glossary#object) but without any in-game existence. They are useful as custom places to store data but also as building blocks in persistent game systems. Since the can be initialized with timing capabilities they can also be used for long-time persistent time keeping (for fast updates other types of timers may be better though). [Read more about Scripts here](Scripts)
|
||||
When we refer to _Scripts_, we generally refer to the `Script` [typeclass](./Typeclasses). Scripts are the mavericks of Evennia - they are like [Objects](./Glossary#object) but without any in-game existence. They are useful as custom places to store data but also as building blocks in persistent game systems. Since the can be initialized with timing capabilities they can also be used for long-time persistent time keeping (for fast updates other types of timers may be better though). [Read more about Scripts here](./Scripts)
|
||||
|
||||
### _session_
|
||||
|
||||
A [Session](Sessions) is a Python object representing a single client connection to the server. A given human player could connect to the game from different clients and each would get a Session (even if you did not allow them to actually log in and get access to an [account](Glossary#account)).
|
||||
A [Session](./Sessions) is a Python object representing a single client connection to the server. A given human player could connect to the game from different clients and each would get a Session (even if you did not allow them to actually log in and get access to an [account](./Glossary#account)).
|
||||
|
||||
Sessions are _not_ [typeclassed](Glossary#typeclass) and has no database persistence. But since they always exist (also when not logged in), they share some common functionality with typeclasses that can be useful for certain game states.
|
||||
Sessions are _not_ [typeclassed](./Glossary#typeclass) and has no database persistence. But since they always exist (also when not logged in), they share some common functionality with typeclasses that can be useful for certain game states.
|
||||
|
||||
### _ticker_
|
||||
|
||||
The [Ticker handler](TickerHandler) runs Evennia's optional 'ticker' system. In other engines, such as [DIKU](https://en.wikipedia.org/wiki/DikuMUD), all game events are processed only at specific intervals called 'ticks'. Evennia has no such technical limitation (events are processed whenever needed) but using a fixed tick can still be useful for certain types of game systems, like combat. Ticker Handler allows you to emulate any number of tick rates (not just one) and subscribe actions to be called when those ticks come around.
|
||||
The [Ticker handler](./TickerHandler) runs Evennia's optional 'ticker' system. In other engines, such as [DIKU](https://en.wikipedia.org/wiki/DikuMUD), all game events are processed only at specific intervals called 'ticks'. Evennia has no such technical limitation (events are processed whenever needed) but using a fixed tick can still be useful for certain types of game systems, like combat. Ticker Handler allows you to emulate any number of tick rates (not just one) and subscribe actions to be called when those ticks come around.
|
||||
|
||||
### _typeclass_
|
||||
|
||||
The [typeclass](Typeclasses) is an Evennia-specific term. A typeclass allows developers to work with database-persistent objects as if they were normal Python objects. It makes use of specific [Django](Glossary#django) features to link a Python class to a database table. Sometimes we refer to such code entities as _being typeclassed_.
|
||||
The [typeclass](./Typeclasses) is an Evennia-specific term. A typeclass allows developers to work with database-persistent objects as if they were normal Python objects. It makes use of specific [Django](./Glossary#django) features to link a Python class to a database table. Sometimes we refer to such code entities as _being typeclassed_.
|
||||
|
||||
Evennia's main typeclasses are [Account](Glossary#account), [Object](Glossary#object), [Script](Glossary#script) and [Channel](Glossary#channel). Children of the base class (such as [Character](Glossary#character)) will use the same database table as the parent, but can have vastly different Python capabilities (and persistent features through [Attributes](Glossary#attributes) and [Tags](Glossary#tags). A typeclass can be coded and treated pretty much like any other Python class except it must inherit (at any distance) from one of the base typeclasses. Also, creating a new instance of a typeclass will add a new row to the database table to which it is linked.
|
||||
Evennia's main typeclasses are [Account](./Glossary#account), [Object](./Glossary#object), [Script](./Glossary#script) and [Channel](./Glossary#channel). Children of the base class (such as [Character](./Glossary#character)) will use the same database table as the parent, but can have vastly different Python capabilities (and persistent features through [Attributes](./Glossary#attributes) and [Tags](./Glossary#tags). A typeclass can be coded and treated pretty much like any other Python class except it must inherit (at any distance) from one of the base typeclasses. Also, creating a new instance of a typeclass will add a new row to the database table to which it is linked.
|
||||
|
||||
The [core](Glossary#core) typeclasses in the Evennia library are all named `DefaultAccount`, `DefaultObject` etc. When you initialize your [game dir] you automatically get empty children of these, called `Account`, `Object` etc that you can start working with.
|
||||
The [core](./Glossary#core) typeclasses in the Evennia library are all named `DefaultAccount`, `DefaultObject` etc. When you initialize your [game dir] you automatically get empty children of these, called `Account`, `Object` etc that you can start working with.
|
||||
|
||||
### _twisted_
|
||||
|
||||
[Twisted](https://twistedmatrix.com/trac/) is a heavy-duty asynchronous networking engine. It is one of Evennia's two major library dependencies (the other one is [Django](Glossary#django)). Twisted is what "runs" Evennia - it handles Evennia's event loop. Twisted also has the building blocks we need to construct network protocols and communicate with the outside world; such as our MUD-custom version of Telnet, Telnet+SSL, SSH, webclient-websockets etc. Twisted also runs our integrated web server, serving the Django-based website for your game.
|
||||
[Twisted](https://twistedmatrix.com/trac/) is a heavy-duty asynchronous networking engine. It is one of Evennia's two major library dependencies (the other one is [Django](./Glossary#django)). Twisted is what "runs" Evennia - it handles Evennia's event loop. Twisted also has the building blocks we need to construct network protocols and communicate with the outside world; such as our MUD-custom version of Telnet, Telnet+SSL, SSH, webclient-websockets etc. Twisted also runs our integrated web server, serving the Django-based website for your game.
|
||||
|
||||
### _virtualenv_
|
||||
|
||||
|
|
@ -190,7 +190,7 @@ Usage:
|
|||
- `<folder_name>\Scripts\activate` (windows)
|
||||
- `deactivate` - turn off the currently activated virtualenv.
|
||||
|
||||
A virtualenv is 'activated' only for the console/terminal it was started in, but it's safe to activate the same virtualenv many times in different windows if you want. Once activated, all Python packages now installed with [pip](Glossary#pip) will install to `evenv` rather than to a global location like `/usr/local/bin` or `C:\Program Files`.
|
||||
A virtualenv is 'activated' only for the console/terminal it was started in, but it's safe to activate the same virtualenv many times in different windows if you want. Once activated, all Python packages now installed with [pip](./Glossary#pip) will install to `evenv` rather than to a global location like `/usr/local/bin` or `C:\Program Files`.
|
||||
|
||||
> Note that if you have root/admin access you *could* install Evennia globally just fine, without using a virtualenv. It's strongly discouraged and considered bad practice though. Experienced Python developers tend to rather create one new virtualenv per project they are working on, to keep the varying installs cleanly separated from one another.
|
||||
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@ Guest accounts are turned off by default. To activate, add this to your `game/se
|
|||
|
||||
GUEST_ENABLED = True
|
||||
|
||||
Henceforth users can use `connect guest` (in the default command set) to login with a guest account. You may need to change your [Connection Screen](Connection-Screen) to inform them of this possibility. Guest accounts work differently from normal accounts - they are automatically *deleted* whenever the user logs off or the server resets (but not during a reload). They are literally re-usable throw-away accounts.
|
||||
Henceforth users can use `connect guest` (in the default command set) to login with a guest account. You may need to change your [Connection Screen](./Connection-Screen) to inform them of this possibility. Guest accounts work differently from normal accounts - they are automatically *deleted* whenever the user logs off or the server resets (but not during a reload). They are literally re-usable throw-away accounts.
|
||||
|
||||
You can add a few more variables to your `settings.py` file to customize your guests:
|
||||
|
||||
- `BASE_GUEST_TYPECLASS` - the python-path to the default [typeclass](Typeclasses) for guests. Defaults to `"typeclasses.accounts.Guest"`.
|
||||
- `PERMISSION_GUEST_DEFAULT` - [permission level](Locks) for guest accounts. Defaults to `"Guests"`, which is the lowest permission level in the hierarchy.
|
||||
- `BASE_GUEST_TYPECLASS` - the python-path to the default [typeclass](./Typeclasses) for guests. Defaults to `"typeclasses.accounts.Guest"`.
|
||||
- `PERMISSION_GUEST_DEFAULT` - [permission level](./Locks) for guest accounts. Defaults to `"Guests"`, which is the lowest permission level in the hierarchy.
|
||||
- `GUEST_START_LOCATION` - the `#dbref` to the starting location newly logged-in guests should appear at. Defaults to `"#2` (Limbo).
|
||||
- `GUEST_HOME` - guest home locations. Defaults to Limbo as well.
|
||||
- `GUEST_LIST` - this is a list holding the possible guest names to use when entering the game. The length of this list also sets how many guests may log in at the same time. By default this is a list of nine names from `"Guest1"` to `"Guest9"`.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# Help System Tutorial
|
||||
|
||||
|
||||
**Before doing this tutorial you will probably want to read the intro in [Basic Web tutorial](Web-Tutorial).** Reading the three first parts of the [Django tutorial](https://docs.djangoproject.com/en/1.9/intro/tutorial01/) might help as well.
|
||||
**Before doing this tutorial you will probably want to read the intro in [Basic Web tutorial](./Web-Tutorial).** Reading the three first parts of the [Django tutorial](https://docs.djangoproject.com/en/1.9/intro/tutorial01/) might help as well.
|
||||
|
||||
This tutorial will show you how to access the help system through your website. Both help commands and regular help entries will be visible, depending on the logged-in user or an anonymous character.
|
||||
|
||||
|
|
|
|||
|
|
@ -47,20 +47,20 @@ The text at the very top of the command class definition is the class' `__doc__`
|
|||
|
||||
You should also supply the `help_category` class property if you can; this helps to group help entries together for people to more easily find them. See the `help` command in-game to see the default categories. If you don't specify the category, "General" is assumed.
|
||||
|
||||
If you don't want your command to be picked up by the auto-help system at all (like if you want to write its docs manually using the info in the next section or you use a [cmdset](Command-Sets) that has its own help functionality) you can explicitly set `auto_help` class property to `False` in your command definition.
|
||||
If you don't want your command to be picked up by the auto-help system at all (like if you want to write its docs manually using the info in the next section or you use a [cmdset](./Command-Sets) that has its own help functionality) you can explicitly set `auto_help` class property to `False` in your command definition.
|
||||
|
||||
Alternatively, you can keep the advantages of *auto-help* in commands, but control the display of command helps. You can do so by overriding the command's `get_help()` method. By default, this method will return the class docstring. You could modify it to add custom behavior: the text returned by this method will be displayed to the character asking for help in this command.
|
||||
|
||||
## Database help entries
|
||||
|
||||
These are all help entries not involving commands (this is handled automatically by the [Command Auto-help system](Help-System#command-auto-help-system)). Non-automatic help entries describe how your particular game is played - its rules, world descriptions and so on.
|
||||
These are all help entries not involving commands (this is handled automatically by the [Command Auto-help system](./Help-System#command-auto-help-system)). Non-automatic help entries describe how your particular game is played - its rules, world descriptions and so on.
|
||||
|
||||
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 and also partial matches will be found.
|
||||
- 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.
|
||||
- locks - a [lock definition](Locks). This can be used to limit access to this help entry, maybe because it's staff-only or otherwise meant to be restricted. Help commands check for `access_type`s `view` and `edit`. An example of a lock string would be `view:perm(Builders)`.
|
||||
- locks - a [lock definition](./Locks). This can be used to limit access to this help entry, maybe because it's staff-only or otherwise meant to be restricted. Help commands check for `access_type`s `view` and `edit`. An example of a lock string would be `view:perm(Builders)`.
|
||||
|
||||
You can create new help entries in code by using `evennia.create_help_entry()`.
|
||||
|
||||
|
|
@ -81,6 +81,6 @@ Using `@sethelp` you can add, delete and append text to existing entries. By def
|
|||
|
||||
If the category *Roleplaying* did not already 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):
|
||||
You can, finally, define a lock for the help entry by following the category with a [lock definition](./Locks):
|
||||
|
||||
> @sethelp/add emote, Roleplaying, view:all() = Emoting is ...
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ If you'd like to help develop Evennia more hands-on, here are some ways to get g
|
|||
- Look through our [online documentation wiki]([online documentation wiki](index)) and see if you can help improve or expand the documentation (even small things like fixing typos!). You don't need any particular permissions to edit the wiki.
|
||||
- Send a message to our [discussion group][group] and/or our [IRC chat][chat] asking about what needs doing, along with what your interests and skills are.
|
||||
- Take a look at our [issue tracker][issues] and see if there's something you feel like taking on. [here are bugs][issues-master] that need fixes. At any given time there may also be some [bounties][issues-bounties] open - these are issues members of the community has put up money to see fixed (if you want to put up a bounty yourself you can do so via our page on [bountysource][bountysource]).
|
||||
- Check out the [Contributing](Contributing) page on how to practically contribute with code using github.
|
||||
- Check out the [Contributing](./Contributing) page on how to practically contribute with code using github.
|
||||
|
||||
... And finally, if you want to help motivate and support development you can also drop some coins in the developer's cup. You can [make a donation via PayPal][paypal] or, even better, [become an Evennia patron on Patreon][patreon]! This is a great way to tip your hat and show that you appreciate the work done with the server! Finally, if you want to encourage the community to resolve a particular
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ pip install python-twitter
|
|||
|
||||
## A basic tweet command
|
||||
|
||||
Evennia doesn't have a `tweet` command out of the box so you need to write your own little [Command](Commands) in order to tweet. If you are unsure about how commands work and how to add them, it can be an idea to go through the [Adding a Command Tutorial](Adding-Command-Tutorial) before continuing.
|
||||
Evennia doesn't have a `tweet` command out of the box so you need to write your own little [Command](./Commands) in order to tweet. If you are unsure about how commands work and how to add them, it can be an idea to go through the [Adding a Command Tutorial](./Adding-Command-Tutorial) before continuing.
|
||||
|
||||
You can create the command in a separate command module (something like `mygame/commands/tweet.py`) or together with your other custom commands, as you prefer.
|
||||
|
||||
|
|
@ -76,7 +76,7 @@ class CmdTweet(Command):
|
|||
|
||||
Be sure to substitute your own actual API/Access keys and secrets in the appropriate places.
|
||||
|
||||
We default to limiting tweet access to players with `Developers`-level access *or* to those players that have the permission "tweet" (allow individual characters to tweet with `@perm/player playername = tweet`). You may change the [lock](Locks) as you feel is appropriate. Change the overall permission to `Players` if you want everyone to be able to tweet.
|
||||
We default to limiting tweet access to players with `Developers`-level access *or* to those players that have the permission "tweet" (allow individual characters to tweet with `@perm/player playername = tweet`). You may change the [lock](./Locks) as you feel is appropriate. Change the overall permission to `Players` if you want everyone to be able to tweet.
|
||||
|
||||
Now add this command to your default command set (e.g in `mygame/commands/defalt_cmdsets.py`") and reload the server. From now on those with access can simply use `tweet <message>` to see the tweet posted from the game's Twitter account.
|
||||
|
||||
|
|
@ -89,4 +89,4 @@ This shows only a basic tweet setup, other things to do could be:
|
|||
* Changing locks to make tweeting open to more people
|
||||
* Echo your tweets to an in-game channel
|
||||
|
||||
Rather than using an explicit command you can set up a Script to send automatic tweets, for example to post updated game stats. See the [Tweeting Game Stats tutorial](Tutorial-Tweeting-Game-Stats) for help.
|
||||
Rather than using an explicit command you can set up a Script to send automatic tweets, for example to post updated game stats. See the [Tweeting Game Stats tutorial](./Tutorial-Tweeting-Game-Stats) for help.
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
_Disambiguation: This page is related to using IRC inside an Evennia game. To join the official Evennia IRC chat, connect to irc.freenode.net and join #evennia. Alternatively, you can [join our Discord](https://discord.gg/NecFePw), which is mirrored to IRC._
|
||||
|
||||
[IRC (Internet Relay Chat)](http://en.wikipedia.org/wiki/Internet_Relay_Chat) 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) to an IRC channel you can communicate also with people not on an mud themselves. You can also use IRC if you are only running your Evennia MUD locally on your computer (your game doesn'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.
|
||||
[IRC (Internet Relay Chat)](http://en.wikipedia.org/wiki/Internet_Relay_Chat) 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) to an IRC channel you can communicate also with people not on an mud themselves. You can also use IRC if you are only running your Evennia MUD locally on your computer (your game doesn'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.
|
||||
|
||||
## Configuring IRC
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ game.
|
|||
|
||||
- Put everything you would need to look up in a rule book into a module in `mygame/world`. Hide away as much as you can. Think of it as a black box (or maybe the code representation of an all-knowing game master). The rest of your game will ask this black box questions and get answers back. Exactly how it arrives at those results should not need to be known outside the box. Doing it this way makes it easier to change and update things in one place later.
|
||||
- Store only the minimum stuff you need with each game object. That is, if your Characters need values for Health, a list of skills etc, store those things on the Character - don't store how to roll or change them.
|
||||
- Next is to determine just how you want to store things on your Objects and Characters. You can choose to either store things as individual [Attributes](Attributes), like `character.db.STR=34` and `character.db.Hunting_skill=20`. But you could also use some custom storage method, like a dictionary `character.db.skills = {"Hunting":34, "Fishing":20, ...}`. A much more fancy solution is to look at the Ainneve [Trait handler](https://github.com/evennia/ainneve/blob/master/world/traits.py). Finally you could even go with a [custom django model](New-Models). Which is the better depends on your game and the complexity of your system.
|
||||
- Next is to determine just how you want to store things on your Objects and Characters. You can choose to either store things as individual [Attributes](./Attributes), like `character.db.STR=34` and `character.db.Hunting_skill=20`. But you could also use some custom storage method, like a dictionary `character.db.skills = {"Hunting":34, "Fishing":20, ...}`. A much more fancy solution is to look at the Ainneve [Trait handler](https://github.com/evennia/ainneve/blob/master/world/traits.py). Finally you could even go with a [custom django model](./New-Models). Which is the better depends on your game and the complexity of your system.
|
||||
- Make a clear [API](http://en.wikipedia.org/wiki/Application_programming_interface) into your rules. That is, make methods/functions that you feed with, say, your Character and which skill you want to check. That is, you want something similar to this:
|
||||
|
||||
```python
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# Inputfuncs
|
||||
|
||||
|
||||
An *inputfunc* is an Evennia function that handles a particular input (an [inputcommand](OOB)) from the client. The inputfunc is the last destination for the inputcommand along the [ingoing message path](Messagepath#the-ingoing-message-path). The inputcommand always has the form `(commandname, (args), {kwargs})` and Evennia will use this to try to find and call an inputfunc on the form
|
||||
An *inputfunc* is an Evennia function that handles a particular input (an [inputcommand](./OOB)) from the client. The inputfunc is the last destination for the inputcommand along the [ingoing message path](./Messagepath#the-ingoing-message-path). The inputcommand always has the form `(commandname, (args), {kwargs})` and Evennia will use this to try to find and call an inputfunc on the form
|
||||
|
||||
```python
|
||||
def commandname(session, *args, **kwargs):
|
||||
|
|
@ -31,7 +31,7 @@ Evennia defines a few default inputfuncs to handle the common cases. These are d
|
|||
- Input: `("text", (textstring,), {})`
|
||||
- Output: Depends on Command triggered
|
||||
|
||||
This is the most common of inputcommands, and the only one supported by every traditional mud. The argument is usually what the user sent from their command line. Since all text input from the user like this is considered a [Command](Commands), this inputfunc will do things like nick-replacement and then pass on the input to the central Commandhandler.
|
||||
This is the most common of inputcommands, and the only one supported by every traditional mud. The argument is usually what the user sent from their command line. Since all text input from the user like this is considered a [Command](./Commands), this inputfunc will do things like nick-replacement and then pass on the input to the central Commandhandler.
|
||||
|
||||
### echo
|
||||
|
||||
|
|
@ -110,7 +110,7 @@ Retrieves a value from the Character or Account currently controlled by this Ses
|
|||
"interval": secs, "stop": False})`
|
||||
- Output: Depends on the repeated function. Will return `("text", (repeatlist),{}` with a list of accepted names if given an unfamiliar callback name.
|
||||
|
||||
This will tell evennia to repeatedly call a named function at a given interval. Behind the scenes this will set up a [Ticker](TickerHandler). Only previously acceptable functions are possible to repeat-call in this way, you'll need to overload this inputfunc to add the ones you want to offer. By default only two example functions are allowed, "test1" and "test2", which will just echo a text back at the given interval. Stop the repeat by sending `"stop": True` (note that you must include both the callback name and interval for Evennia to know what to stop).
|
||||
This will tell evennia to repeatedly call a named function at a given interval. Behind the scenes this will set up a [Ticker](./TickerHandler). Only previously acceptable functions are possible to repeat-call in this way, you'll need to overload this inputfunc to add the ones you want to offer. By default only two example functions are allowed, "test1" and "test2", which will just echo a text back at the given interval. Stop the repeat by sending `"stop": True` (note that you must include both the callback name and interval for Evennia to know what to stop).
|
||||
|
||||
### unrepeat
|
||||
|
||||
|
|
@ -125,7 +125,7 @@ This is a convenience wrapper for sending "stop" to the `repeat` inputfunc.
|
|||
- Input: `("monitor", (), ("name":field_or_argname, stop=False)`
|
||||
- Output (on change): `("monitor", (), {"name":name, "value":value})`
|
||||
|
||||
This sets up on-object monitoring of Attributes or database fields. Whenever the field or Attribute changes in any way, the outputcommand will be sent. This is using the [MonitorHandler](MonitorHandler) behind the scenes. Pass the "stop" key to stop monitoring. Note that you must supply the name also when stopping to let the system know which monitor should be cancelled.
|
||||
This sets up on-object monitoring of Attributes or database fields. Whenever the field or Attribute changes in any way, the outputcommand will be sent. This is using the [MonitorHandler](./MonitorHandler) behind the scenes. Pass the "stop" key to stop monitoring. Note that you must supply the name also when stopping to let the system know which monitor should be cancelled.
|
||||
|
||||
Only fields/attributes in a whitelist are allowed to be used, you have to overload this function to add more. By default the following fields/attributes can be monitored:
|
||||
|
||||
|
|
|
|||
|
|
@ -67,13 +67,13 @@ Install the latest Evennia in a way that lets you edit the source
|
|||
(evenv) $ pip install --upgrade -e 'git+https://github.com/evennia/evennia#egg=evennia'
|
||||
```
|
||||
|
||||
This step will possibly take quite a while - we are downloading Evennia and are then installing it, building all of the requirements for Evennia to run. If you run into trouble on this step, please see [Troubleshooting](Installing-on-Android#troubleshooting).
|
||||
This step will possibly take quite a while - we are downloading Evennia and are then installing it, building all of the requirements for Evennia to run. If you run into trouble on this step, please see [Troubleshooting](./Installing-on-Android#troubleshooting).
|
||||
|
||||
You can go to the dir where Evennia is installed with `cd $VIRTUAL_ENV/src/evennia`. `git grep (something)` can be handy, as can `git diff`
|
||||
|
||||
### Final steps
|
||||
|
||||
At this point, Evennia is installed on your phone! You can now continue with the original [Getting Started](Getting-Started) instruction, we repeat them here for clarity.
|
||||
At this point, Evennia is installed on your phone! You can now continue with the original [Getting Started](./Getting-Started) instruction, we repeat them here for clarity.
|
||||
|
||||
To start a new game:
|
||||
|
||||
|
|
@ -103,7 +103,7 @@ $ cd ~ && source evenv/bin/activate
|
|||
(evenv) $ evennia start
|
||||
```
|
||||
|
||||
You may wish to look at the [Linux Instructions](Getting-Started#linux-install) for more.
|
||||
You may wish to look at the [Linux Instructions](./Getting-Started#linux-install) for more.
|
||||
|
||||
## Caveats
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ Here `'en'` should be changed to the abbreviation for one of the supported langu
|
|||
|
||||
If you cannot find your language in `evennia/locale/` it's because noone has translated it yet. Alternatively you might have the language but find the translation bad ... You are welcome to help improve the situation!
|
||||
|
||||
To start a new translation you need to first have cloned the Evennia repositry with GIT and activated a python virtualenv as described on the [Getting Started](Getting-Started) page. You now need to `cd` to the `evennia/` directory. This is *not* your created game folder but the main Evennia library folder. If you see a folder `locale/` then you are in the right place. From here you run:
|
||||
To start a new translation you need to first have cloned the Evennia repositry with GIT and activated a python virtualenv as described on the [Getting Started](./Getting-Started) page. You now need to `cd` to the `evennia/` directory. This is *not* your created game folder but the main Evennia library folder. If you see a folder `locale/` then you are in the right place. From here you run:
|
||||
|
||||
evennia makemessages <language-code>
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
- [Discord live blog](https://discordapp.com/channels/517176782357528616/517176782781415434) of the _Blackbirds_ Evennia game project.
|
||||
- [Unreal Engine Evennia plugin](https://www.unrealengine.com/marketplace/en-US/slug/evennia-plugin) - an in-progress Unreal plugin for integrating Evennia with Epic Games' Unreal Engine.
|
||||
- [The dark net/March Hare MUD](https://github.com/thedarknet/evennia) from the 2019 [DEF CON 27](https://www.defcon.org/html/defcon-27/dc-27-index.html) hacker conference in Paris. This is an Evennia game dir with batchcode to build the custom _Hackers_ style cyberspace zone with puzzles and challenges [used during the conference](https://dcdark.net/home#).
|
||||
- [Arx sources](https://github.com/Arx-Game/arxcode) - Open-source code release of the very popular [Arx](http://play.arxmush.org/) Evennia game. [Here are instructions for installing](Arxcode-installing-help)
|
||||
- [Arx sources](https://github.com/Arx-Game/arxcode) - Open-source code release of the very popular [Arx](http://play.arxmush.org/) Evennia game. [Here are instructions for installing](./Arxcode-installing-help)
|
||||
- [Evennia-wiki](https://github.com/vincent-lg/evennia-wiki) - An Evennia-specific Wiki for your website.
|
||||
- [Evcolor](https://github.com/taladan/Pegasus/blob/origin/world/utilities/evcolor) - Optional coloration for Evennia unit-test output.
|
||||
- [Paxboards](https://github.com/aurorachain/paxboards) - Evennia bulletin board system (both for telnet/web).
|
||||
|
|
@ -107,4 +107,4 @@
|
|||
|
||||
### Credits
|
||||
|
||||
- Wiki [Home](index) Icons made by [Freepik](http://www.freepik.com"-title="Freepik">Freepik) from [flaticon.com](http://www.flaticon.com), licensed under [Creative Commons BY 3.0](http://creativecommons.org/licenses/by/3.0).
|
||||
- Wiki [Home](./index) Icons made by [Freepik](http://www.freepik.com"-title="Freepik">Freepik) from [flaticon.com](http://www.flaticon.com), licensed under [Creative Commons BY 3.0](http://creativecommons.org/licenses/by/3.0).
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
# 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), [Objects](Objects), [Scripts](Scripts), [Accounts](Accounts), [Help System](Help-System), [messages](Communications#Msg) and [channels](Communications#Channels)) are accessed through 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), [Objects](./Objects), [Scripts](./Scripts), [Accounts](./Accounts), [Help System](./Help-System), [messages](./Communications#Msg) and [channels](./Communications#Channels)) 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.
|
||||
|
||||
|
|
@ -65,9 +65,9 @@ If you want to make sure the lock is used however, you should pick `access_type`
|
|||
|
||||
Below are the access_types checked by the default commandset.
|
||||
|
||||
- [Commands](Commands)
|
||||
- [Commands](./Commands)
|
||||
- `cmd` - this defines who may call this command at all.
|
||||
- [Objects](Objects):
|
||||
- [Objects](./Objects):
|
||||
- `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 stored on this Object except for the Object itself. By default, Objects share their Commands with anyone in the same location (e.g. so you can 'press' a `Button` object in the room). For Characters and Mobs (who likely only use those Commands for themselves and don't want to share them) this should usually be turned off completely, using something like `call:false()`.
|
||||
- `examine` - who may examine this object's properties.
|
||||
|
|
@ -77,25 +77,25 @@ Below are the access_types checked by the default commandset.
|
|||
- `get`- who may pick up the object and carry it around.
|
||||
- `puppet` - who may "become" this object and control it as their "character".
|
||||
- `attrcreate` - who may create new attributes on the object (default True)
|
||||
- [Characters](Objects#Characters):
|
||||
- [Characters](./Objects#Characters):
|
||||
- Same as for Objects
|
||||
- [Exits](Objects#Exits):
|
||||
- [Exits](./Objects#Exits):
|
||||
- Same as for Objects
|
||||
- `traverse` - who may pass the exit.
|
||||
- [Accounts](Accounts):
|
||||
- [Accounts](./Accounts):
|
||||
- `examine` - who may examine the account's properties.
|
||||
- `delete` - who may delete the account.
|
||||
- `edit` - who may edit the account's attributes and properties.
|
||||
- `msg` - who may send messages to the account.
|
||||
- `boot` - who may boot the account.
|
||||
- [Attributes](Attributes): (only checked by `obj.secure_attr`)
|
||||
- [Attributes](./Attributes): (only checked by `obj.secure_attr`)
|
||||
- `attrread` - see/access attribute
|
||||
- `attredit` - change/delete attribute
|
||||
- [Channels](Communications#Channels):
|
||||
- [Channels](./Communications#Channels):
|
||||
- `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](Help-System):
|
||||
- [HelpEntry](./Help-System):
|
||||
- `examine` - who may view this help entry (usually everyone)
|
||||
- `edit` - who may edit this help entry.
|
||||
|
||||
|
|
@ -160,10 +160,10 @@ Some useful default lockfuncs (see `src/locks/lockfuncs.py` for more):
|
|||
|
||||
- `true()/all()` - give access to everyone
|
||||
- `false()/none()/superuser()` - give access to none. Superusers bypass the check entirely and are thus the only ones who will pass this check.
|
||||
- `perm(perm)` - this tries to match a given `permission` property, on an Account firsthand, on a Character second. See [below](Locks#permissions).
|
||||
- `perm(perm)` - this tries to match a given `permission` property, on an Account firsthand, on a Character second. See [below](./Locks#permissions).
|
||||
- `perm_above(perm)` - like `perm` but requires a "higher" permission level than the one given.
|
||||
- `id(num)/dbref(num)` - checks so the access_object has a certain dbref/id.
|
||||
- `attr(attrname)` - checks if a certain [Attribute](Attributes) exists on accessing_object.
|
||||
- `attr(attrname)` - checks if a certain [Attribute](./Attributes) exists on accessing_object.
|
||||
- `attr(attrname, value)` - checks so an attribute exists on accessing_object *and* has the given value.
|
||||
- `attr_gt(attrname, value)` - checks so accessing_object has a value larger (`>`) than the given value.
|
||||
- `attr_ge, attr_lt, attr_le, attr_ne` - corresponding for `>=`, `<`, `<=` and `!=`.
|
||||
|
|
@ -187,11 +187,11 @@ Note here that the `access_type` can be left to a dummy value since this method
|
|||
|
||||
## Default locks
|
||||
|
||||
Evennia sets up a few basic locks on all new objects and accounts (if we didn't, noone would have any access to anything from the start). This is all defined in the root [Typeclasses](Typeclasses) 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 so as to allow you, its creator, to control and delete the object.
|
||||
Evennia sets up a few basic locks on all new objects and accounts (if we didn't, noone would have any access to anything from the start). This is all defined in the root [Typeclasses](./Typeclasses) 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 so as to allow you, its creator, to control and delete the object.
|
||||
|
||||
# Permissions
|
||||
|
||||
> This section covers the underlying code use of permissions. If you just want to learn how to practically assign permissions in-game, refer to the [Building Permissions](Building-Permissions) page, which details how you use the `perm` command.
|
||||
> This section covers the underlying code use of permissions. If you just want to learn how to practically assign permissions in-game, refer to the [Building Permissions](./Building-Permissions) page, which details how you use the `perm` command.
|
||||
|
||||
A *permission* is simply a list of text strings stored in the handler `permissions` on `Objects` and `Accounts`. Permissions can be used as a convenient way to structure access levels and hierarchies. It is set by the `perm` command. Permissions are especially handled by the `perm()` and `pperm()` lock functions listed above.
|
||||
|
||||
|
|
@ -233,16 +233,16 @@ Selected permission strings can be organized in a *permission hierarchy* by edit
|
|||
|
||||
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 access. So if you have the permission "Admin" you will also pass a lock defined as `perm(Builder)` or any of those levels below "Admin".
|
||||
|
||||
When doing an access check from an [Object](Objects) or Character, the `perm()` lock function will always first use the permissions of any Account connected to that Object before checking for permissions on the Object. In the case of hierarchical permissions (Admins, Builders etc), the Account permission will always be used (this stops an Account from escalating their permission by puppeting a high-level Character). If the permission looked for is not in the hierarchy, an exact match is required, first on the Account and if not found there (or if no Account is connected), then on the Object itself.
|
||||
When doing an access check from an [Object](./Objects) or Character, the `perm()` lock function will always first use the permissions of any Account connected to that Object before checking for permissions on the Object. In the case of hierarchical permissions (Admins, Builders etc), the Account permission will always be used (this stops an Account from escalating their permission by puppeting a high-level Character). If the permission looked for is not in the hierarchy, an exact match is required, first on the Account and if not found there (or if no Account is connected), then on the Object itself.
|
||||
|
||||
Here is how you use `perm` to give an account more permissions:
|
||||
|
||||
perm/account Tommy = Builders
|
||||
perm/account/del Tommy = Builders # remove it again
|
||||
|
||||
Note the use of the `/account` switch. It means you assign the permission to the [Accounts](Accounts) Tommy instead of any [Character](Objects) that also happens to be named "Tommy".
|
||||
Note the use of the `/account` switch. It means you assign the permission to the [Accounts](./Accounts) Tommy instead of any [Character](./Objects) that also happens to be named "Tommy".
|
||||
|
||||
Putting permissions on the *Account* guarantees that they are kept, *regardless* of which Character they are currently puppeting. This is especially important to remember when assigning permissions from the *hierarchy tree* - as mentioned above, an Account's permissions will overrule that of its character. So to be sure to avoid confusion you should generally put hierarchy permissions on the Account, not on their Characters (but see also [quelling](Locks#Quelling)).
|
||||
Putting permissions on the *Account* guarantees that they are kept, *regardless* of which Character they are currently puppeting. This is especially important to remember when assigning permissions from the *hierarchy tree* - as mentioned above, an Account's permissions will overrule that of its character. So to be sure to avoid confusion you should generally put hierarchy permissions on the Account, not on their Characters (but see also [quelling](./Locks#Quelling)).
|
||||
|
||||
Below is an example of an object without any connected account
|
||||
|
||||
|
|
@ -300,7 +300,7 @@ This is how the `create` command sets up new objects. In sequence, this permissi
|
|||
|
||||
## 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) called `box`.
|
||||
Assume we have two objects - one is ourselves (not superuser) and the other is an [Object](./Objects) called `box`.
|
||||
|
||||
> create/drop box
|
||||
> desc box = "This is a very big and heavy box."
|
||||
|
|
@ -320,7 +320,7 @@ Ok, so for testing we made ourselves strong, but not strong enough. Now we need
|
|||
return
|
||||
```
|
||||
|
||||
So the `get` command looks for a lock with the type *get* (not so surprising). It also looks for an [Attribute](Attributes) 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:
|
||||
So the `get` command looks for a lock with the type *get* (not so surprising). It also looks for an [Attribute](./Attributes) 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.
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
This is a small tutorial for customizing your character objects, using the example of letting users turn on and off ANSI color parsing as an example. `@options NOCOLOR=True` will now do what this tutorial shows, but the tutorial subject can be applied to other toggles you may want, as well.
|
||||
|
||||
In the Building guide's [Colors](TextTags#coloured-text) page you can learn how to add color to your game by using special markup. Colors enhance the gaming experience, but not all users want color. Examples would be users working from clients that don't support color, or people with various seeing disabilities that rely on screen readers to play your game. Also, whereas Evennia normally automatically detects if a client supports color, it may get it wrong. Being able to turn it on manually if you know it **should** work could be a nice feature.
|
||||
In the Building guide's [Colors](./TextTags#coloured-text) page you can learn how to add color to your game by using special markup. Colors enhance the gaming experience, but not all users want color. Examples would be users working from clients that don't support color, or people with various seeing disabilities that rely on screen readers to play your game. Also, whereas Evennia normally automatically detects if a client supports color, it may get it wrong. Being able to turn it on manually if you know it **should** work could be a nice feature.
|
||||
|
||||
So here's how to allow those users to remove color. It basically means you implementing a simple configuration system for your characters. This is the basic sequence:
|
||||
|
||||
|
|
@ -17,7 +17,7 @@ So here's how to allow those users to remove color. It basically means you imple
|
|||
|
||||
Create a new module in `mygame/typeclasses` named, for example, `mycharacter.py`. Alternatively you can simply add a new class to 'mygamegame/typeclasses/characters.py'.
|
||||
|
||||
In your new module(or characters.py), create a new [Typeclass](Typeclasses) inheriting from `evennia.DefaultCharacter`. We will also import `evennia.utils.ansi`, which we will use later.
|
||||
In your new module(or characters.py), create a new [Typeclass](./Typeclasses) inheriting from `evennia.DefaultCharacter`. We will also import `evennia.utils.ansi`, which we will use later.
|
||||
|
||||
```python
|
||||
from evennia import Character
|
||||
|
|
@ -29,7 +29,7 @@ In your new module(or characters.py), create a new [Typeclass](Typeclasses) inhe
|
|||
self.db.config_color = True
|
||||
```
|
||||
|
||||
Above we set a simple config value as an [Attribute](Attributes).
|
||||
Above we set a simple config value as an [Attribute](./Attributes).
|
||||
|
||||
Let's make sure that new characters are created of this type. Edit your `mygame/server/conf/settings.py` file and add/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!).
|
||||
|
||||
|
|
@ -127,7 +127,7 @@ class CharacterCmdSet(default_cmds.CharacterCmdSet):
|
|||
|
||||
## More colors
|
||||
|
||||
Apart from ANSI colors, Evennia also supports **Xterm256** colors (See [Colors](TextTags#colored-text)). The `msg()` method supports the `xterm256` keyword for manually activating/deactiving xterm256. It should be easy to expand the above example to allow players to customize xterm256 regardless of if Evennia thinks their client supports it or not.
|
||||
Apart from ANSI colors, Evennia also supports **Xterm256** colors (See [Colors](./TextTags#colored-text)). The `msg()` method supports the `xterm256` keyword for manually activating/deactiving xterm256. It should be easy to expand the above example to allow players to customize xterm256 regardless of if Evennia thinks their client supports it or not.
|
||||
|
||||
To get a better understanding of how `msg()` works with keywords, you can try this as superuser:
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ The client sends data to Evennia in two ways.
|
|||
- When first connecting, the client can send data to the server about its
|
||||
capabilities. This is things like "I support xterm256 but not unicode" and is
|
||||
mainly used when a Telnet client connects. This is called a "handshake" and
|
||||
will generally set some flags on the [Portal Session](Portal-And-Server) that
|
||||
will generally set some flags on the [Portal Session](./Portal-And-Server) that
|
||||
are later synced to the Server Session. Since this is not something the player
|
||||
controls, we'll not explore this further here.
|
||||
- The client can send an *inputcommand* to the server. Traditionally this only
|
||||
|
|
@ -31,7 +31,7 @@ The client sends data to Evennia in two ways.
|
|||
the client may send commands based on a timer or some trigger.
|
||||
|
||||
Exactly how the inputcommand looks when it travels from the client to Evennia
|
||||
depends on the [Protocol](Custom-Protocols) used:
|
||||
depends on the [Protocol](./Custom-Protocols) used:
|
||||
- Telnet: A string. If GMCP or MSDP OOB protocols are used, this string will
|
||||
be formatted in a special way, but it's still a raw string. If Telnet SSL is
|
||||
active, the string will be encrypted.
|
||||
|
|
@ -60,7 +60,7 @@ This inputcommand-structure is pickled together with the unique session-id of th
|
|||
|
||||
### ServerSessionHandler (ingoing)
|
||||
|
||||
On the Server side, the AMP unpickles the data and associates the session id with the server-side [Session](Sessions). Data and Session are passed to the server-side `SessionHandler.data_in`. This in turn calls `ServerSession.data_in()`
|
||||
On the Server side, the AMP unpickles the data and associates the session id with the server-side [Session](./Sessions). Data and Session are passed to the server-side `SessionHandler.data_in`. This in turn calls `ServerSession.data_in()`
|
||||
|
||||
### ServerSession (ingoing)
|
||||
|
||||
|
|
@ -78,7 +78,7 @@ If a matching inputfunc is found, it will be called with the Session and the inp
|
|||
|
||||
### Inputfunc
|
||||
|
||||
The [Inputfunc](Inputfuncs) must be on the form `func(session, *args, **kwargs)`. An exception is the `default` inputfunc which has form `default(session, cmdname, *args, **kwargs)`, where `cmdname` is the un-matched inputcommand string.
|
||||
The [Inputfunc](./Inputfuncs) must be on the form `func(session, *args, **kwargs)`. An exception is the `default` inputfunc which has form `default(session, cmdname, *args, **kwargs)`, where `cmdname` is the un-matched inputcommand string.
|
||||
|
||||
This is where the message's path diverges, since just what happens next depends on the type of inputfunc was triggered. In the example of sending "look", the inputfunc is named "text". It will pass the argument to the `cmdhandler` which will eventually lead to the `look` command being executed.
|
||||
|
||||
|
|
@ -135,7 +135,7 @@ In the *ServerSessionhandler*, the keywords from the `msg` method are collated i
|
|||
|
||||
This will intelligently convert different input to the same form. So `msg("Hello")` will end up as an outputcommand `("text", ("Hello",), {})`.
|
||||
|
||||
This is also the point where [Inlinefuncs](TextTags#inline-functions) are parsed, depending on the session to receive the data. Said data is pickled together with the Session id then sent over the AMP bridge.
|
||||
This is also the point where [Inlinefuncs](./TextTags#inline-functions) are parsed, depending on the session to receive the data. Said data is pickled together with the Session id then sent over the AMP bridge.
|
||||
|
||||
### PortalSessionHandler (outgoing)
|
||||
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@ MONITOR_HANDLER.add(obj, fieldname, callback,
|
|||
|
||||
```
|
||||
|
||||
- `obj` ([Typeclassed](Typeclasses) entity) - the object to monitor. Since this must be typeclassed, it means you can't monitor changes on [Sessions](Sessions) with the monitorhandler, for example.
|
||||
- `fieldname` (str) - the name of a field or [Attribute](Attributes) on `obj`. If you want to monitor a database field you must specify its full name, including the starting `db_` (like `db_key`, `db_location` etc). Any names not starting with `db_` are instead assumed to be the names of Attributes. This difference matters, since the MonitorHandler will automatically know to watch the `db_value` field of the Attribute.
|
||||
- `obj` ([Typeclassed](./Typeclasses) entity) - the object to monitor. Since this must be typeclassed, it means you can't monitor changes on [Sessions](./Sessions) with the monitorhandler, for example.
|
||||
- `fieldname` (str) - the name of a field or [Attribute](./Attributes) on `obj`. If you want to monitor a database field you must specify its full name, including the starting `db_` (like `db_key`, `db_location` etc). Any names not starting with `db_` are instead assumed to be the names of Attributes. This difference matters, since the MonitorHandler will automatically know to watch the `db_value` field of the Attribute.
|
||||
- `callback`(callable) - This will be called as `callback(fieldname=fieldname, obj=obj, **kwargs)` when the field updates.
|
||||
- `idstring` (str) - this is used to separate multiple monitors on the same object and fieldname. This is required in order to properly identify and remove the monitor later. It's also used for saving it.
|
||||
- `persistent` (bool) - if True, the monitor will survive a server reboot.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# NPC shop Tutorial
|
||||
|
||||
This tutorial will describe how to make an NPC-run shop. We will make use of the [EvMenu](EvMenu) system to present shoppers with a menu where they can buy things from the store's stock.
|
||||
This tutorial will describe how to make an NPC-run shop. We will make use of the [EvMenu](./EvMenu) system to present shoppers with a menu where they can buy things from the store's stock.
|
||||
|
||||
Our shop extends over two rooms - a "front" room open to the shop's customers and a locked "store room" holding the wares the shop should be able to sell. We aim for the following features:
|
||||
|
||||
|
|
@ -13,7 +13,7 @@ Our shop extends over two rooms - a "front" room open to the shop's customers an
|
|||
|
||||
### The shop menu
|
||||
|
||||
We want to show a menu to the customer where they can list, examine and buy items in the store. This menu should change depending on what is currently for sale. Evennia's *EvMenu* utility will manage the menu for us. It's a good idea to [read up on EvMenu](EvMenu) if you are not familiar with it.
|
||||
We want to show a menu to the customer where they can list, examine and buy items in the store. This menu should change depending on what is currently for sale. Evennia's *EvMenu* utility will manage the menu for us. It's a good idea to [read up on EvMenu](./EvMenu) if you are not familiar with it.
|
||||
|
||||
#### Designing the menu
|
||||
|
||||
|
|
@ -135,7 +135,7 @@ When the user choose the "buy" option, EvMenu will execute the `exec` instructio
|
|||
|
||||
#### The command to start the menu
|
||||
|
||||
We could *in principle* launch the shopping menu the moment a customer steps into our shop room, but this would probably be considered pretty annoying. It's better to create a [Command](Commands) for customers to explicitly wanting to shop around.
|
||||
We could *in principle* launch the shopping menu the moment a customer steps into our shop room, but this would probably be considered pretty annoying. It's better to create a [Command](./Commands) for customers to explicitly wanting to shop around.
|
||||
|
||||
```python
|
||||
# mygame/typeclasses/npcshop.py
|
||||
|
|
@ -164,7 +164,7 @@ class CmdBuy(Command):
|
|||
startnode="menunode_shopfront")
|
||||
```
|
||||
|
||||
This will launch the menu. The `EvMenu` instance is initialized with the path to this very module - since the only global functions available in this module are our menu nodes, this will work fine (you could also have put those in a separate module). We now just need to put this command in a [CmdSet](Command-Sets) so we can add it correctly to the game:
|
||||
This will launch the menu. The `EvMenu` instance is initialized with the path to this very module - since the only global functions available in this module are our menu nodes, this will work fine (you could also have put those in a separate module). We now just need to put this command in a [CmdSet](./Command-Sets) so we can add it correctly to the game:
|
||||
|
||||
```python
|
||||
from evennia import CmdSet
|
||||
|
|
@ -181,7 +181,7 @@ There are really only two things that separate our shop from any other Room:
|
|||
- The shop has the `storeroom` Attribute set on it, pointing to a second (completely normal) room.
|
||||
- It has the `ShopCmdSet` stored on itself. This makes the `buy` command available to users entering the shop.
|
||||
|
||||
For testing we could easily add these features manually to a room using `@py` or other admin commands. Just to show how it can be done we'll instead make a custom [Typeclass](Typeclasses) for the shop room and make a small command that builders can use to build both the shop and the storeroom at once.
|
||||
For testing we could easily add these features manually to a room using `@py` or other admin commands. Just to show how it can be done we'll instead make a custom [Typeclass](./Typeclasses) for the shop room and make a small command that builders can use to build both the shop and the storeroom at once.
|
||||
|
||||
```python
|
||||
# bottom of mygame/typeclasses/npcshop.py
|
||||
|
|
@ -252,9 +252,9 @@ class CmdBuildShop(Command):
|
|||
self.caller.msg("The shop %s was created!" % shop)
|
||||
```
|
||||
|
||||
Our typeclass is simple and so is our `buildshop` command. The command (which is for Builders only) just takes the name of the shop and builds the front room and a store room to go with it (always named `"<shopname>-storage"`. It connects the rooms with a two-way exit. You need to add `CmdBuildShop` [to the default cmdset](Adding-Command-Tutorial#step-2-adding-the-command-to-a-default-cmdset) before you can use it. Once having created the shop you can now `@teleport` to it or `@open` a new exit to it. You could also easily expand the above command to automatically create exits to and from the new shop from your current location.
|
||||
Our typeclass is simple and so is our `buildshop` command. The command (which is for Builders only) just takes the name of the shop and builds the front room and a store room to go with it (always named `"<shopname>-storage"`. It connects the rooms with a two-way exit. You need to add `CmdBuildShop` [to the default cmdset](./Adding-Command-Tutorial#step-2-adding-the-command-to-a-default-cmdset) before you can use it. Once having created the shop you can now `@teleport` to it or `@open` a new exit to it. You could also easily expand the above command to automatically create exits to and from the new shop from your current location.
|
||||
|
||||
To avoid customers walking in and stealing everything, we create a [Lock](Locks) on the storage door. It's a simple lock that requires the one entering to carry an object named `<shopname>-storekey`. We even create such a key object and drop it in the shop for the new shop keeper to pick up.
|
||||
To avoid customers walking in and stealing everything, we create a [Lock](./Locks) on the storage door. It's a simple lock that requires the one entering to carry an object named `<shopname>-storekey`. We even create such a key object and drop it in the shop for the new shop keeper to pick up.
|
||||
|
||||
> If players are given the right to name their own objects, this simple lock is not very secure and you need to come up with a more robust lock-key solution.
|
||||
|
||||
|
|
@ -270,4 +270,4 @@ We now have a functioning shop and an easy way for Builders to create it. All yo
|
|||
|
||||
Fixing these issues are left as an exercise.
|
||||
|
||||
If you want to keep the shop fully NPC-run you could add a [Script](Scripts) to restock the shop's store room regularly. This shop example could also easily be owned by a human Player (run for them by a hired NPC) - the shop owner would get the key to the store room and be responsible for keeping it well stocked.
|
||||
If you want to keep the shop fully NPC-run you could add a [Script](./Scripts) to restock the shop's store room regularly. This shop example could also easily be owned by a human Player (run for them by a hired NPC) - the shop owner would get the key to the store room and be responsible for keeping it well stocked.
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
*Note: This is considered an advanced topic.*
|
||||
|
||||
Evennia offers many convenient ways to store object data, such as via Attributes or Scripts. This is sufficient for most use cases. But if you aim to build a large stand-alone system, trying to squeeze your storage requirements into those may be more complex than you bargain for. Examples may be to store guild data for guild members to be able to change, tracking the flow of money across a game-wide economic system or implement other custom game systems that requires the storage of custom data in a quickly accessible way. Whereas [Tags](Tags) or [Scripts](Scripts) can handle many situations, sometimes things may be easier to handle by adding your own database model.
|
||||
Evennia offers many convenient ways to store object data, such as via Attributes or Scripts. This is sufficient for most use cases. But if you aim to build a large stand-alone system, trying to squeeze your storage requirements into those may be more complex than you bargain for. Examples may be to store guild data for guild members to be able to change, tracking the flow of money across a game-wide economic system or implement other custom game systems that requires the storage of custom data in a quickly accessible way. Whereas [Tags](./Tags) or [Scripts](./Scripts) can handle many situations, sometimes things may be easier to handle by adding your own database model.
|
||||
|
||||
## Overview of database tables
|
||||
|
||||
|
|
@ -39,7 +39,7 @@ Evennia uses [Django](https://docs.djangoproject.com), which abstracts away the
|
|||
|
||||
Here is how you add your own database table/models:
|
||||
|
||||
1. In Django lingo, we will create a new "application" - a subsystem under the main Evennia program. For this example we'll call it "myapp". Run the following (you need to have a working Evennia running before you do this, so make sure you have run the steps in [Getting Started](Getting-Started) first):
|
||||
1. In Django lingo, we will create a new "application" - a subsystem under the main Evennia program. For this example we'll call it "myapp". Run the following (you need to have a working Evennia running before you do this, so make sure you have run the steps in [Getting Started](./Getting-Started) first):
|
||||
|
||||
cd mygame/world
|
||||
evennia startapp myapp
|
||||
|
|
@ -58,7 +58,7 @@ interested in for now is `models.py`. In `models.py` you define your model(s). E
|
|||
evennia makemigrations myapp
|
||||
evennia migrate
|
||||
|
||||
This will add your new database table to the database. If you have put your game under version control (if not, [you should](Version-Control)), don't forget to `git add myapp/*` to add all items to version control.
|
||||
This will add your new database table to the database. If you have put your game under version control (if not, [you should](./Version-Control)), don't forget to `git add myapp/*` to add all items to version control.
|
||||
|
||||
## Defining your models
|
||||
|
||||
|
|
@ -82,7 +82,7 @@ class MyDataStore(models.Model):
|
|||
|
||||
We create four fields: two character fields of limited length and one text field which has no maximum length. Finally we create a field containing the current time of us creating this object.
|
||||
|
||||
> The `db_date_created` field, with exactly this name, is *required* if you want to be able to store instances of your custom model in an Evennia [Attribute](Attributes). It will automatically be set upon creation and can after that not be changed. Having this field will allow you to do e.g. `obj.db.myinstance = mydatastore`. If you know you'll never store your model instances in Attributes the `db_date_created` field is optional.
|
||||
> The `db_date_created` field, with exactly this name, is *required* if you want to be able to store instances of your custom model in an Evennia [Attribute](./Attributes). It will automatically be set upon creation and can after that not be changed. Having this field will allow you to do e.g. `obj.db.myinstance = mydatastore`. If you know you'll never store your model instances in Attributes the `db_date_created` field is optional.
|
||||
|
||||
You don't *have* to start field names with `db_`, this is an Evennia convention. It's nevertheless recommended that you do use `db_`, partly for clarity and consistency with Evennia (if you ever want to share your code) and partly for the case of you later deciding to use Evennia's `SharedMemoryModel` parent down the line.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# Nicks
|
||||
|
||||
|
||||
*Nicks*, short for *Nicknames* is a system allowing an object (usually a [Account](Accounts)) to assign custom replacement names for other game entities.
|
||||
*Nicks*, short for *Nicknames* is a system allowing an object (usually a [Account](./Accounts)) 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 used to map a different way *you alone* can refer to that entity. Nicks are also commonly used to replace your input text which means you can create your own aliases to default commands.
|
||||
|
||||
|
|
@ -60,7 +60,7 @@ You can also use [shell-type wildcards](http://www.linfo.org/wildcard.html):
|
|||
|
||||
## Coding with nicks
|
||||
|
||||
Nicks are stored as the `Nick` database model and are referred from the normal Evennia [object](Objects) through the `nicks` property - this is known as the *NickHandler*. The NickHandler offers effective error checking, searches and conversion.
|
||||
Nicks are stored as the `Nick` database model and are referred from the normal Evennia [object](./Objects) through the `nicks` property - this is known as the *NickHandler*. The NickHandler offers effective error checking, searches and conversion.
|
||||
|
||||
```python
|
||||
# A command/channel nick:
|
||||
|
|
@ -84,11 +84,11 @@ Nicks are stored as the `Nick` database model and are referred from the normal E
|
|||
|
||||
In a command definition you can reach the nick handler through `self.caller.nicks`. See the `nick` command in `evennia/commands/default/general.py` for more examples.
|
||||
|
||||
As a last note, The Evennia [channel](Communications) alias systems are using nicks with the `nick_type="channel"` in order to allow users to create their own custom aliases to channels.
|
||||
As a last note, The Evennia [channel](./Communications) alias systems are using nicks with the `nick_type="channel"` in order to allow users to create their own custom aliases to channels.
|
||||
|
||||
# Advanced note
|
||||
|
||||
Internally, nicks are [Attributes](Attributes) saved with the `db_attrype` set to "nick" (normal Attributes has this set to `None`).
|
||||
Internally, nicks are [Attributes](./Attributes) saved with the `db_attrype` set to "nick" (normal Attributes has this set to `None`).
|
||||
|
||||
The nick stores the replacement data in the Attribute.db_value field as a tuple with four fields `(regex_nick, template_string, raw_nick, raw_template)`. Here `regex_nick` is the converted regex representation of the `raw_nick` and the `template-string` is a version of the `raw_template` prepared for efficient replacement of any `$`- type markers. The `raw_nick` and `raw_template` are basically the unchanged strings you enter to the `nick` command (with unparsed `$` etc).
|
||||
|
||||
|
|
|
|||
|
|
@ -4,13 +4,13 @@ OOB, or Out-Of-Band, means sending data between Evennia and the user's client wi
|
|||
|
||||
## Briefly on input/outputcommands
|
||||
|
||||
Inside Evennia, all server-client communication happens in the same way (so plain text is also an 'OOB message' as far as Evennia is concerned). The message follows the [Message Path](Messagepath). You should read up on that if you are unfamiliar with it. As the message travels along the path it has a standardized internal form: a tuple with a string, a tuple and a dict:
|
||||
Inside Evennia, all server-client communication happens in the same way (so plain text is also an 'OOB message' as far as Evennia is concerned). The message follows the [Message Path](./Messagepath). You should read up on that if you are unfamiliar with it. As the message travels along the path it has a standardized internal form: a tuple with a string, a tuple and a dict:
|
||||
|
||||
("cmdname", (args), {kwargs})
|
||||
|
||||
This is often referred to as an *inputcommand* or *outputcommand*, depending on the direction it's traveling. The end point for an inputcommand, (the 'Evennia-end' of the message path) is a matching [Inputfunc](Inputfuncs). This function is called as `cmdname(session, *args, **kwargs)` where `session` is the Session-source of the command. Inputfuncs can easily be added by the developer to support/map client commands to actions inside Evennia (see the [inputfunc](Inputfuncs) page for more details).
|
||||
This is often referred to as an *inputcommand* or *outputcommand*, depending on the direction it's traveling. The end point for an inputcommand, (the 'Evennia-end' of the message path) is a matching [Inputfunc](./Inputfuncs). This function is called as `cmdname(session, *args, **kwargs)` where `session` is the Session-source of the command. Inputfuncs can easily be added by the developer to support/map client commands to actions inside Evennia (see the [inputfunc](./Inputfuncs) page for more details).
|
||||
|
||||
When a message is outgoing (at the 'Client-end' of the message path) the outputcommand is handled by a matching *Outputfunc*. This is responsible for converting the internal Evennia representation to a form suitable to send over the wire to the Client. Outputfuncs are hard-coded. Which is chosen and how it processes the outgoing data depends on the nature of the client it's connected to. The only time one would want to add new outputfuncs is as part of developing support for a new Evennia [Protocol](Custom-Protocols).
|
||||
When a message is outgoing (at the 'Client-end' of the message path) the outputcommand is handled by a matching *Outputfunc*. This is responsible for converting the internal Evennia representation to a form suitable to send over the wire to the Client. Outputfuncs are hard-coded. Which is chosen and how it processes the outgoing data depends on the nature of the client it's connected to. The only time one would want to add new outputfuncs is as part of developing support for a new Evennia [Protocol](./Custom-Protocols).
|
||||
|
||||
## Sending and receiving an OOB message
|
||||
|
||||
|
|
@ -33,7 +33,7 @@ Which commands you can send depends on the client. If the client does not suppor
|
|||
|
||||
> Remember that a given message may go to multiple clients with different capabilities. So unless you turn off telnet completely and only rely on the webclient, you should never rely on non-`text` OOB messages always reaching all targets.
|
||||
|
||||
[Inputfuncs](Inputfuncs) lists the default inputfuncs available to handle incoming OOB messages. To accept more you need to add more inputfuncs (see that page for more info).
|
||||
[Inputfuncs](./Inputfuncs) lists the default inputfuncs available to handle incoming OOB messages. To accept more you need to add more inputfuncs (see that page for more info).
|
||||
|
||||
## Supported OOB protocols
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# 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) entities.
|
||||
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) entities.
|
||||
|
||||
## How to create your own object types
|
||||
|
||||
|
|
@ -34,20 +34,20 @@ What the `@create` command actually *does* is to use `evennia.create_object`. Yo
|
|||
new_rose = create_object("typeclasses.flowers.Rose", key="MyRose")
|
||||
```
|
||||
|
||||
(The `@create` command will auto-append the most likely path to your typeclass, if you enter the call manually you have to give the full path to the class. The `create.create_object` function is powerful and should be used for all coded object creating (so this is what you use when defining your own building commands). Check out the `ev.create_*` functions for how to build other entities like [Scripts](Scripts)).
|
||||
(The `@create` command will auto-append the most likely path to your typeclass, if you enter the call manually you have to give the full path to the class. The `create.create_object` function is powerful and should be used for all coded object creating (so this is what you use when defining your own building commands). Check out the `ev.create_*` functions for how to build other entities like [Scripts](./Scripts)).
|
||||
|
||||
This particular Rose 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, which is pretty pointless since you will usually want to change this at build time (using the `@desc` command or using the [Spawner](Spawner-and-Prototypes)). The `Object` typeclass offers many more hooks that is available to use though - see next section.
|
||||
This particular Rose 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, which is pretty pointless since you will usually want to change this at build time (using the `@desc` command or using the [Spawner](./Spawner-and-Prototypes)). The `Object` typeclass offers many more hooks that is available to use though - see next section.
|
||||
|
||||
## Properties and functions on Objects
|
||||
|
||||
Beyond the properties assigned to all [typeclassed](Typeclasses) objects (see that page for a list of those), the Object also has the following custom properties:
|
||||
Beyond the properties assigned to all [typeclassed](./Typeclasses) objects (see that page for a list of those), the Object also has the following custom properties:
|
||||
|
||||
- `aliases` - a handler that allows you to add and remove aliases from this object. Use `aliases.add()` to add a new alias and `aliases.remove()` to remove one.
|
||||
- `location` - a reference to the object currently containing 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 safety.
|
||||
- `destination` - this holds a reference to another object this object links to in some way. Its main use is for [Exits](Objects#Exits), it's otherwise usually unset.
|
||||
- `nicks` - as opposed to aliases, a [Nick](Nicks) holds a convenient nickname replacement for a real name, word or sequence, only valid for this object. This mainly makes sense if the Object is used as a game character - it can then store briefer shorts, example so as to quickly reference game commands or other characters. Use nicks.add(alias, realname) to add a new one.
|
||||
- `account` - this holds a reference to a connected [Account](Accounts) controlling this object (if any). Note that this is set also if the controlling account is *not* currently online - to test if an account is online, use the `has_account` property instead.
|
||||
- `destination` - this holds a reference to another object this object links to in some way. Its main use is for [Exits](./Objects#Exits), it's otherwise usually unset.
|
||||
- `nicks` - as opposed to aliases, a [Nick](./Nicks) holds a convenient nickname replacement for a real name, word or sequence, only valid for this object. This mainly makes sense if the Object is used as a game character - it can then store briefer shorts, example so as to quickly reference game commands or other characters. Use nicks.add(alias, realname) to add a new one.
|
||||
- `account` - this holds a reference to a connected [Account](./Accounts) controlling this object (if any). Note that this is set also if the controlling account is *not* currently online - to test if an account is online, use the `has_account` property instead.
|
||||
- `sessions` - if `account` field is set *and the account is online*, this is a list of all active sessions (server connections) to contact them through (it may be more than one if multiple connections are allowed in settings).
|
||||
- `has_account` - a shorthand for checking if an *online* account is currently connected to this object.
|
||||
- `contents` - this returns a list referencing all objects 'inside' this object (i,e. which has this object set as their `location`).
|
||||
|
|
@ -55,8 +55,8 @@ Beyond the properties assigned to all [typeclassed](Typeclasses) objects (see th
|
|||
|
||||
The last two properties are special:
|
||||
|
||||
- `cmdset` - this is a handler that stores all [command sets](Commands#Command_Sets) defined on the object (if any).
|
||||
- `scripts` - this is a handler that manages [Scripts](Scripts) attached to the object (if any).
|
||||
- `cmdset` - this is a handler that stores all [command sets](./Commands#Command_Sets) defined on the object (if any).
|
||||
- `scripts` - this is a handler that manages [Scripts](./Scripts) attached to the object (if any).
|
||||
|
||||
The Object also has a host of useful utility functions. See the function headers in `src/objects/objects.py` for their arguments and more details.
|
||||
|
||||
|
|
@ -65,7 +65,7 @@ The Object also has a host of useful utility functions. See the function headers
|
|||
- `search()` - this is a convenient shorthand to search for a specific object, at a given location or globally. It's mainly useful when defining commands (in which case the object executing the command is named `caller` and one can do `caller.search()` to find objects in the room to operate on).
|
||||
- `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) to *and* from this object.
|
||||
- `clear_exits()` - will delete all [Exits](./Objects#Exits) 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()`.
|
||||
|
|
@ -78,10 +78,10 @@ There are three special subclasses of *Object* in default Evennia - *Characters*
|
|||
|
||||
### Characters
|
||||
|
||||
Characters are objects controlled by [Accounts](Accounts). When a new Account
|
||||
Characters are objects controlled by [Accounts](./Accounts). When a new Account
|
||||
logs in to Evennia for the first time, a new `Character` object is created and
|
||||
the Account object is assigned to the `account` attribute. A `Character` object
|
||||
must have a [Default Commandset](Commands#Command_Sets) set on itself at
|
||||
must have a [Default Commandset](./Commands#Command_Sets) set on itself at
|
||||
creation, or the account will not be able to issue any commands! If you just
|
||||
inherit your own class from `evennia.DefaultCharacter` and make sure to use
|
||||
`super()` to call the parent methods you should be fine. In
|
||||
|
|
@ -94,13 +94,13 @@ to modify.
|
|||
|
||||
### 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) 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.
|
||||
*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) 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) using an access_type called *traverse* and also make use of a few hook methods for giving feedback if the traversal fails. See `evennia.DefaultExit` for more info. In `mygame/typeclasses/exits.py` there is an empty `Exit` class for you to modify.
|
||||
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) using an access_type called *traverse* and also make use of a few hook methods for giving feedback if the traversal fails. See `evennia.DefaultExit` for more info. In `mygame/typeclasses/exits.py` there is an empty `Exit` class for you to modify.
|
||||
|
||||
The process of traversing an exit is as follows:
|
||||
|
||||
1. The traversing `obj` sends a command that matches the Exit-command name on the Exit object. The [cmdhandler](Commands) detects this and triggers the command defined on the Exit. Traversal always involves the "source" (the current location) and the `destination` (this is stored on the Exit object).
|
||||
1. The traversing `obj` sends a command that matches the Exit-command name on the Exit object. The [cmdhandler](./Commands) detects this and triggers the command defined on the Exit. Traversal always involves the "source" (the current location) and the `destination` (this is stored on the Exit object).
|
||||
1. The Exit command checks the `traverse` lock on the Exit object
|
||||
1. The Exit command triggers `at_traverse(obj, destination)` on the Exit object.
|
||||
1. In `at_traverse`, `object.move_to(destination)` is triggered. This triggers the following hooks, in order:
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ Evennia will by default accept incoming connections on all interfaces (`0.0.0.0`
|
|||
|
||||
### Settings example
|
||||
|
||||
You can connect Evennia to the Internet without any changes to your settings. The default settings are easy to use but are not necessarily the safest. You can customize your online presence in your [settings file](Server-Conf#settings-file). To have Evennia recognize changed port settings you have to do a full `evennia reboot` to also restart the Portal and not just the Server component.
|
||||
You can connect Evennia to the Internet without any changes to your settings. The default settings are easy to use but are not necessarily the safest. You can customize your online presence in your [settings file](./Server-Conf#settings-file). To have Evennia recognize changed port settings you have to do a full `evennia reboot` to also restart the Portal and not just the Server component.
|
||||
|
||||
Below is an example of a simple set of settings, mostly using the defaults. Evennia will require access to five computer ports, of which three (only) should be open to the outside world. Below we continue to assume that our server address is `203.0.113.0`.
|
||||
|
||||
|
|
@ -127,7 +127,7 @@ SSH_INTERFACES = ['0.0.0.0']
|
|||
AMP_PORT = 4006
|
||||
```
|
||||
|
||||
The `AMP_PORT` is required to work, since this is the internal port linking Evennia's [Server and Portal](Portal-And-Server) components together. The other ports are encrypted ports that may be useful for custom protocols but are otherwise not used.
|
||||
The `AMP_PORT` is required to work, since this is the internal port linking Evennia's [Server and Portal](./Portal-And-Server) components together. The other ports are encrypted ports that may be useful for custom protocols but are otherwise not used.
|
||||
|
||||
### Lockdown mode
|
||||
|
||||
|
|
@ -141,7 +141,7 @@ To register, stand in your game dir, run
|
|||
|
||||
evennia connections
|
||||
|
||||
and follow the instructions. See the [Game index page](Evennia-Game-Index) for more details.
|
||||
and follow the instructions. See the [Game index page](./Evennia-Game-Index) for more details.
|
||||
|
||||
## SSL
|
||||
|
||||
|
|
@ -174,7 +174,7 @@ Also, on Freenode visit the #letsencrypt channel for assistance from the communi
|
|||
The only process missing from all of the above documentation is how to pass verification. This is how Let's Encrypt verifies that you have control over your domain (not necessarily ownership, it's Domain Validation (DV)). This can be done either with configuring a certain path on your web server or through a TXT record in your DNS. Which one you will want to do is a personal preference, but can also be based on your hosting choice. In a controlled/cPanel environment, you will most likely have to use DNS verification.
|
||||
|
||||
## Relevant SSL Proxy Setup Information
|
||||
- [Apache webserver configuration](Apache-Config) (optional)
|
||||
- [Apache webserver configuration](./Apache-Config) (optional)
|
||||
- [HAProxy Config](HAProxy-Config-(Optional))
|
||||
|
||||
## Hosting locally or remotely?
|
||||
|
|
@ -199,7 +199,7 @@ What we showed above is by far the simplest and probably cheapest option: Run Ev
|
|||
|
||||
#### Setting up your own machine as a server
|
||||
|
||||
[The first section](Online-Setup#connecting-from-the-outside) of this page describes how to do this and allow users to connect to the IP address of your machine/router.
|
||||
[The first section](./Online-Setup#connecting-from-the-outside) of this page describes how to do this and allow users to connect to the IP address of your machine/router.
|
||||
|
||||
A complication with using a specific IP address like this is that your home IP might not remain the same. Many ISPs (Internet Service Providers) allocates a *dynamic* IP to you which could change at any time. When that happens, that IP you told people to go to will be worthless. Also, that long string of numbers is not very pretty, is it? It's hard to remember and not easy to use in marketing your game. What you need is to alias it to a more sensible domain name - an alias that follows you around also when the IP changes.
|
||||
|
||||
|
|
@ -223,7 +223,7 @@ The options you probably need to look for are *shell account services*, *VPS:es*
|
|||
- Usually runs a Linux flavor, making it easy to install Evennia.
|
||||
- Support. You don't need to maintain the server hardware. If your house burns down, at least your game stays online. Many services guarantee a certain level of up-time and also do regular backups for you. Make sure to check, some offer lower rates in exchange for you yourself being fully responsible for your data/backups.
|
||||
- Usually offers a fixed domain name, so no need to mess with IP addresses.
|
||||
- May have the ability to easily deploy [docker](Running-Evennia-in-Docker) versions of evennia and/or your game.
|
||||
- May have the ability to easily deploy [docker](./Running-Evennia-in-Docker) versions of evennia and/or your game.
|
||||
|
||||
**Disadvantages**
|
||||
- Might be pretty expensive (more so than a web hotel). Note that Evennia will normally need at least 100MB RAM and likely much more for a large production game.
|
||||
|
|
@ -232,9 +232,9 @@ The options you probably need to look for are *shell account services*, *VPS:es*
|
|||
|
||||
#### Installing Evennia on a remote server
|
||||
|
||||
Firstly, if you are familiar with server infrastructure, consider using [Docker](Running-Evennia-in-Docker) to deploy your game to the remote server; it will likely ease installation and deployment. Docker images may be a little confusing if you are completely new to them though.
|
||||
Firstly, if you are familiar with server infrastructure, consider using [Docker](./Running-Evennia-in-Docker) to deploy your game to the remote server; it will likely ease installation and deployment. Docker images may be a little confusing if you are completely new to them though.
|
||||
|
||||
If not using docker, and assuming you know how to connect to your account over ssh/PuTTy, you should be able to follow the [Getting Started](Getting-Started) instructions normally. You only need Python and GIT pre-installed; these should both be available on any servers (if not you should be able to easily ask for them to be installed). On a VPS or Cloud service you can install them yourself as needed.
|
||||
If not using docker, and assuming you know how to connect to your account over ssh/PuTTy, you should be able to follow the [Getting Started](./Getting-Started) instructions normally. You only need Python and GIT pre-installed; these should both be available on any servers (if not you should be able to easily ask for them to be installed). On a VPS or Cloud service you can install them yourself as needed.
|
||||
|
||||
If `virtualenv` is not available and you can't get it, you can download it (it's just a single file) from [the virtualenv pypi](https://pypi.python.org/pypi/virtualenv). Using `virtualenv` you can install everything without actually needing to have further `root` access. Ports might be an issue, so make sure you know which ports are available to use and reconfigure Evennia accordingly.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# Parsing command arguments, theory and best practices
|
||||
|
||||
|
||||
This tutorial will elaborate on the many ways one can parse command arguments. The first step after [adding a command](Adding-Command-Tutorial) usually is to parse its arguments. There are lots of ways to do it, but some are indeed better than others and this tutorial will try to present them.
|
||||
This tutorial will elaborate on the many ways one can parse command arguments. The first step after [adding a command](./Adding-Command-Tutorial) usually is to parse its arguments. There are lots of ways to do it, but some are indeed better than others and this tutorial will try to present them.
|
||||
|
||||
If you're a Python beginner, this tutorial might help you a lot. If you're already familiar with Python syntax, this tutorial might still contain useful information. There are still a lot of things I find in the standard library that come as a surprise, though they were there all along. This might be true for others.
|
||||
|
||||
|
|
@ -544,7 +544,7 @@ After this quick tour of some `str` methods, we'll take a look at some Evennia-s
|
|||
|
||||
One very common task is to convert a `str` into an Evennia object. Take the previous example: having `"book"` in a variable is great, but we would prefer to know what the user is talking about... what is this `"book"`?
|
||||
|
||||
To get an object from a string, we perform an Evennia search. Evennia provides a `search` method on all typeclassed objects (you will most likely use the one on characters or accounts). This method supports a very wide array of arguments and has [its own tutorial](Tutorial-Searching-For-Objects). Some examples of useful cases follow:
|
||||
To get an object from a string, we perform an Evennia search. Evennia provides a `search` method on all typeclassed objects (you will most likely use the one on characters or accounts). This method supports a very wide array of arguments and has [its own tutorial](./Tutorial-Searching-For-Objects). Some examples of useful cases follow:
|
||||
|
||||
### Local searches
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
|
||||
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](Start-Stop-Reload).
|
||||
inside the game or from the command line as described [here](./Start-Stop-Reload).
|
||||
|
||||
If you are new to the concept, the main purpose of separating the two is to have accounts connect to
|
||||
the Portal but keep the MUD running on the Server. This way one can restart/reload the game (the
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ Python comes with its own profiler, named cProfile (this is for cPython, no test
|
|||
|
||||
evennia --profiler start
|
||||
|
||||
This will start Evennia with the Server component running (in daemon mode) under cProfile. You could instead try `--profile` with the `portal` argument to profile the Portal (you would then need to [start the Server separately](Start-Stop-Reload)).
|
||||
This will start Evennia with the Server component running (in daemon mode) under cProfile. You could instead try `--profile` with the `portal` argument to profile the Portal (you would then need to [start the Server separately](./Start-Stop-Reload)).
|
||||
|
||||
Please note that while the profiler is running, your process will use a lot more memory than usual. Memory usage is even likely to climb over time. So don't leave it running perpetually but monitor it carefully (for example using the `top` command on Linux or the Task Manager's memory display on Windows).
|
||||
|
||||
|
|
|
|||
|
|
@ -3,14 +3,14 @@
|
|||
This is the first part of our beginner's guide to the basics of using Python with Evennia. It's aimed at you with limited or no programming/Python experience. But also if you are an experienced programmer new to Evennia or Python you might still pick up a thing or two. It is by necessity brief and low on detail. There are countless Python guides and tutorials, books and videos out there for learning more in-depth - use them!
|
||||
|
||||
**Contents:**
|
||||
- [Evennia Hello world](Python-basic-introduction#evennia-hello-world)
|
||||
- [Importing modules](Python-basic-introduction#importing-modules)
|
||||
- [Parsing Python errors](Python-basic-introduction#parsing-python-errors)
|
||||
- [Our first function](Python-basic-introduction#our-first-function)
|
||||
- [Looking at the log](Python-basic-introduction#looking-at-the-log)
|
||||
- (continued in [part 2](Python-basic-tutorial-part-two))
|
||||
- [Evennia Hello world](./Python-basic-introduction#evennia-hello-world)
|
||||
- [Importing modules](./Python-basic-introduction#importing-modules)
|
||||
- [Parsing Python errors](./Python-basic-introduction#parsing-python-errors)
|
||||
- [Our first function](./Python-basic-introduction#our-first-function)
|
||||
- [Looking at the log](./Python-basic-introduction#looking-at-the-log)
|
||||
- (continued in [part 2](./Python-basic-tutorial-part-two))
|
||||
|
||||
This quickstart assumes you have [gotten Evennia started](Getting-Started). You should make sure that you are able to see the output from the server in the console from which you started it. Log into the game either with a mud client on `localhost:4000` or by pointing a web browser to `localhost:4001/webclient`. Log in as your superuser (the user you created during install).
|
||||
This quickstart assumes you have [gotten Evennia started](./Getting-Started). You should make sure that you are able to see the output from the server in the console from which you started it. Log into the game either with a mud client on `localhost:4000` or by pointing a web browser to `localhost:4001/webclient`. Log in as your superuser (the user you created during install).
|
||||
|
||||
Below, lines starting with a single `>` means command input.
|
||||
|
||||
|
|
@ -170,4 +170,4 @@ evennia --log
|
|||
|
||||
This will show the log. New entries will show up in real time. Whenever you want to leave the log, enter `Ctrl-C` or `Cmd-C` depending on your system. As a game dev it is important to look at the log output when working in Evennia - many errors will only appear with full details here. You may sometimes have to scroll up in the history if you miss it.
|
||||
|
||||
This tutorial is continued in [Part 2](Python-basic-tutorial-part-two), where we'll start learning about objects and to explore the Evennia library.
|
||||
This tutorial is continued in [Part 2](./Python-basic-tutorial-part-two), where we'll start learning about objects and to explore the Evennia library.
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
# Python basic tutorial part two
|
||||
|
||||
[In the first part](Python-basic-introduction) of this Python-for-Evennia basic tutorial we learned how to run some simple Python code from inside the game. We also made our first new *module* containing a *function* that we called. Now we're going to start exploring the very important subject of *objects*.
|
||||
[In the first part](./Python-basic-introduction) of this Python-for-Evennia basic tutorial we learned how to run some simple Python code from inside the game. We also made our first new *module* containing a *function* that we called. Now we're going to start exploring the very important subject of *objects*.
|
||||
|
||||
**Contents:**
|
||||
- [On the subject of objects](Python-basic-tutorial-part-two#on-the-subject-of-objects)
|
||||
- [Exploring the Evennia library](Python-basic-tutorial-part-two#exploring-the-evennia-library)
|
||||
- [Tweaking our Character class](Python-basic-tutorial-part-two#tweaking-our-character-class)
|
||||
- [The Evennia shell](Python-basic-tutorial-part-two#the-evennia-shell)
|
||||
- [Where to go from here](Python-basic-tutorial-part-two#where-to-go-from-here)
|
||||
- [On the subject of objects](./Python-basic-tutorial-part-two#on-the-subject-of-objects)
|
||||
- [Exploring the Evennia library](./Python-basic-tutorial-part-two#exploring-the-evennia-library)
|
||||
- [Tweaking our Character class](./Python-basic-tutorial-part-two#tweaking-our-character-class)
|
||||
- [The Evennia shell](./Python-basic-tutorial-part-two#the-evennia-shell)
|
||||
- [Where to go from here](./Python-basic-tutorial-part-two#where-to-go-from-here)
|
||||
|
||||
### On the subject of objects
|
||||
|
||||
|
|
@ -114,7 +114,7 @@ evennia/
|
|||
evennia/
|
||||
...
|
||||
```
|
||||
There are lots of things in there. There are some docs but most of those have to do with the distribution of Evennia and does not concern us right now. The `evennia` subfolder is what we are looking for. *This* is what you are accessing when you do `from evennia import ...`. It's set up by Evennia as a good place to find modules when the server starts. The exact layout of the Evennia library [is covered by our directory overview](Directory-Overview#evennia-library-layout). You can also explore it [online on github](https://github.com/evennia/evennia/tree/master/evennia).
|
||||
There are lots of things in there. There are some docs but most of those have to do with the distribution of Evennia and does not concern us right now. The `evennia` subfolder is what we are looking for. *This* is what you are accessing when you do `from evennia import ...`. It's set up by Evennia as a good place to find modules when the server starts. The exact layout of the Evennia library [is covered by our directory overview](./Directory-Overview#evennia-library-layout). You can also explore it [online on github](https://github.com/evennia/evennia/tree/master/evennia).
|
||||
|
||||
The structure of the library directly reflects how you import from it.
|
||||
|
||||
|
|
@ -123,7 +123,7 @@ The structure of the library directly reflects how you import from it.
|
|||
- You could also do `import evennia`. You would then have to enter the full `evennia.utils.utils.justify(...)` every time you use it. Using `from` to only import the things you need is usually easier and more readable.
|
||||
- See [this overview](http://effbot.org/zone/import-confusion.htm) about the different ways to import in Python.
|
||||
|
||||
Now, remember that our `characters.py` module did `from evennia import DefaultCharacter`. But if we look at the contents of the `evennia` folder, there is no `DefaultCharacter` anywhere! This is because Evennia gives a large number of optional "shortcuts", known as [the "flat" API](Evennia-API). The intention is to make it easier to remember where to find stuff. The flat API is defined in that weirdly named `__init__.py` file. This file just basically imports useful things from all over Evennia so you can more easily find them in one place.
|
||||
Now, remember that our `characters.py` module did `from evennia import DefaultCharacter`. But if we look at the contents of the `evennia` folder, there is no `DefaultCharacter` anywhere! This is because Evennia gives a large number of optional "shortcuts", known as [the "flat" API](./Evennia-API). The intention is to make it easier to remember where to find stuff. The flat API is defined in that weirdly named `__init__.py` file. This file just basically imports useful things from all over Evennia so you can more easily find them in one place.
|
||||
|
||||
We could [just look at the documenation](github:evennia#typeclasses) to find out where we can look at our `DefaultCharacter` parent. But for practice, let's figure it out. Here is where `DefaultCharacter` [is imported from](https://github.com/evennia/evennia/blob/master/evennia/__init__.py#L188) inside `__init__.py`:
|
||||
|
||||
|
|
@ -147,7 +147,7 @@ is the same thing, just a little easier to remember.
|
|||
|
||||
> To access the shortcuts of the flat API you *must* use `from evennia import
|
||||
> ...`. Using something like `import evennia.DefaultCharacter` will not work.
|
||||
> See [more about the Flat API here](Evennia-API).
|
||||
> See [more about the Flat API here](./Evennia-API).
|
||||
|
||||
|
||||
### Tweaking our Character class
|
||||
|
|
@ -199,7 +199,7 @@ class DefaultCharacter(DefaultObject):
|
|||
|
||||
... And so on (you can see the full [class online here](https://github.com/evennia/evennia/blob/master/evennia/objects/objects.py#L1915)). Here we have functional code! These methods may not be directly visible in `Character` back in our game dir, but they are still available since `Character` is a child of `DefaultCharacter` above. Here is a brief summary of the methods we find in `DefaultCharacter` (follow in the code to see if you can see roughly where things happen)::
|
||||
|
||||
- `basetype_setup` is called by Evennia only once, when a Character is first created. In the `DefaultCharacter` class it sets some particular [Locks](Locks) so that people can't pick up and puppet Characters just like that. It also adds the [Character Cmdset](Command-Sets) so that Characters always can accept command-input (this should usually not be modified - the normal hook to override is `at_object_creation`, which is called after `basetype_setup` (it's in the parent)).
|
||||
- `basetype_setup` is called by Evennia only once, when a Character is first created. In the `DefaultCharacter` class it sets some particular [Locks](./Locks) so that people can't pick up and puppet Characters just like that. It also adds the [Character Cmdset](./Command-Sets) so that Characters always can accept command-input (this should usually not be modified - the normal hook to override is `at_object_creation`, which is called after `basetype_setup` (it's in the parent)).
|
||||
- `at_after_move` makes it so that every time the Character moves, the `look` command is automatically fired (this would not make sense for just any regular Object).
|
||||
- `at_pre_puppet` is called when an Account begins to puppet this Character. When not puppeted, the Character is hidden away to a `None` location. This brings it back to the location it was in before. Without this, "headless" Characters would remain in the game world just standing around.
|
||||
- `at_post_puppet` is called when puppeting is complete. It echoes a message to the room that his Character has now connected.
|
||||
|
|
@ -301,8 +301,7 @@ If you did this call from your game dir you will now be in a Python prompt manag
|
|||
|
||||
IPython ...
|
||||
...
|
||||
In [1]:
|
||||
|
||||
In [1]:
|
||||
IPython has some very nice ways to explore what Evennia has to offer.
|
||||
|
||||
> import evennia
|
||||
|
|
@ -324,10 +323,10 @@ This will show us the changed code we just did. Having a window with IPython run
|
|||
|
||||
### Where to go from here
|
||||
|
||||
This should give you a running start using Python with Evennia. If you are completely new to programming or Python you might want to look at a more formal Python tutorial. You can find links and resources [on our link page](Links).
|
||||
This should give you a running start using Python with Evennia. If you are completely new to programming or Python you might want to look at a more formal Python tutorial. You can find links and resources [on our link page](./Links).
|
||||
|
||||
We have touched upon many of the concepts here but to use Evennia and to be able to follow along in the code, you will need basic understanding of Python [modules](http://docs.python.org/2/tutorial/modules.html), [variables](http://www.tutorialspoint.com/python/python_variable_types.htm), [conditional statements](http://docs.python.org/tutorial/controlflow.html#if-statements), [loops](http://docs.python.org/tutorial/controlflow.html#for-statements), [functions](http://docs.python.org/tutorial/controlflow.html#defining-functions), [lists, dictionaries, list comprehensions](http://docs.python.org/tutorial/datastructures.html) and [string formatting](http://docs.python.org/tutorial/introduction.html#strings). You should also have a basic understanding of [object-oriented programming](http://www.tutorialspoint.com/python/python_classes_objects.htm) and what Python [Classes](http://docs.python.org/tutorial/classes.html) are.
|
||||
|
||||
Once you have familiarized yourself, or if you prefer to pick Python up as you go, continue to one of the beginning-level [Evennia tutorials](Tutorials) to gradually build up your understanding.
|
||||
Once you have familiarized yourself, or if you prefer to pick Python up as you go, continue to one of the beginning-level [Evennia tutorials](./Tutorials) to gradually build up your understanding.
|
||||
|
||||
Good luck!
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ The property `blist` is now `[1,2,3,4]` whereas `object.db.mylist` remains uncha
|
|||
|
||||
### Commands are matched by name *or* alias
|
||||
|
||||
When merging [command sets](Commands) it's important to remember that command objects are identified *both* by key *or* alias. So if you have a command with a key `look` and an alias `ls`, introducing another command with a key `ls` will be assumed by the system to be *identical* to the first one. This usually means merging cmdsets will overload one of them depending on priority. Whereas this is logical once you know how command objects are handled, it may be confusing if you are just looking at the command strings thinking they are parsed as-is.
|
||||
When merging [command sets](./Commands) it's important to remember that command objects are identified *both* by key *or* alias. So if you have a command with a key `look` and an alias `ls`, introducing another command with a key `ls` will be assumed by the system to be *identical* to the first one. This usually means merging cmdsets will overload one of them depending on priority. Whereas this is logical once you know how command objects are handled, it may be confusing if you are just looking at the command strings thinking they are parsed as-is.
|
||||
|
||||
### Objects turning to `DefaultObject`
|
||||
|
||||
|
|
@ -63,7 +63,7 @@ The moral of the story-- it can be dangerous to tinker with magic methods on typ
|
|||
|
||||
### Known upstream bugs
|
||||
|
||||
- There is currently (Autumn 2017) a bug in the `zope.interface` installer on some Linux Ubuntu distributions (notably Ubuntu 16.04 LTS). Zope is a dependency of Twisted. The error manifests in the server not starting with an error that `zope.interface` is not found even though `pip list` shows it's installed. The reason is a missing empty `__init__.py` file at the root of the zope package. If the virtualenv is named "evenv" as suggested in the [Getting Started](Getting-Started) instructions, use the following command to fix it:
|
||||
- There is currently (Autumn 2017) a bug in the `zope.interface` installer on some Linux Ubuntu distributions (notably Ubuntu 16.04 LTS). Zope is a dependency of Twisted. The error manifests in the server not starting with an error that `zope.interface` is not found even though `pip list` shows it's installed. The reason is a missing empty `__init__.py` file at the root of the zope package. If the virtualenv is named "evenv" as suggested in the [Getting Started](./Getting-Started) instructions, use the following command to fix it:
|
||||
|
||||
```shell
|
||||
touch evenv/local/lib/python2.7/site-packages/zope/__init__.py
|
||||
|
|
|
|||
|
|
@ -31,4 +31,4 @@ That's it, really. New Evennia updates will now show up as a one-line title and
|
|||
|
||||
@rss2chan/delete rss = https://github.com/evennia/evennia/commits/master.atom
|
||||
|
||||
You can connect any number of RSS feeds to a channel this way. You could also connect them to the same channels as [IRC](IRC) to have the feed echo to external chat channels as well.
|
||||
You can connect any number of RSS feeds to a channel this way. You could also connect them to the same channels as [IRC](./IRC) to have the feed echo to external chat channels as well.
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ Having run this (see next section for a description of what's what), you will be
|
|||
evennia|docker /usr/src/game $
|
||||
```
|
||||
|
||||
This is a normal shell prompt. We are in the `/usr/src/game` location inside the docker container. If you had anything in the folder you started from, you should see it here (with `ls`) since we mounted the current directory to `usr/src/game` (with `-v` above). You have the `evennia` command available and can now proceed to create a new game as per the [Getting Started](Getting-Started) instructions (you can skip the virtualenv and install 'globally' in the container though).
|
||||
This is a normal shell prompt. We are in the `/usr/src/game` location inside the docker container. If you had anything in the folder you started from, you should see it here (with `ls`) since we mounted the current directory to `usr/src/game` (with `-v` above). You have the `evennia` command available and can now proceed to create a new game as per the [Getting Started](./Getting-Started) instructions (you can skip the virtualenv and install 'globally' in the container though).
|
||||
|
||||
You can run Evennia from inside this container if you want to, it's like you are root in a little isolated Linux environment. To exit the container and all processes in there, press `Ctrl-D`. If you created a new game folder, you will find that it has appeared on-disk.
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||

|
||||
*(right-click and choose your browser's equivalent of "view image" to see it full size)*
|
||||
|
||||
This screenshot shows a vanilla [install](Getting-Started) of the just started Evennia MUD server. In the bottom window we can see the log messages from the running server.
|
||||
This screenshot shows a vanilla [install](./Getting-Started) of the just started Evennia MUD server. In the bottom window we can see the log messages from the running server.
|
||||
|
||||
In the top left window we see the default website of our new game displayed in a web browser (it has shrunk to accomodate the smaller screen). Evennia contains its own webserver to serve this page. The default site shows some brief info about the database. From here you can also reach Django's *admin interface* for editing the database online.
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
|
||||
*Scripts* are the out-of-character siblings to the in-character
|
||||
[Objects](Objects). Scripts are so flexible that the "Script" is a bit limiting
|
||||
[Objects](./Objects). Scripts are so flexible that the "Script" is a bit limiting
|
||||
- we had to pick something to name them after all. Other possible names
|
||||
(depending on what you'd use them for) would be `OOBObjects`,
|
||||
`StorageContainers` or `TimerObjects`.
|
||||
|
|
@ -14,7 +14,7 @@ Scripts can be used for many different things in Evennia:
|
|||
- They can work as timers and tickers - anything that may change with Time. But
|
||||
they can also have no time dependence at all. Note though that if all you want
|
||||
is just to have an object method called repeatedly, you should consider using
|
||||
the [TickerHandler](TickerHandler) which is more limited but is specialized on
|
||||
the [TickerHandler](./TickerHandler) which is more limited but is specialized on
|
||||
just this task.
|
||||
- They can describe State changes. A Script is an excellent platform for
|
||||
hosting a persistent, but unique system handler. For example, a Script could be
|
||||
|
|
@ -22,11 +22,11 @@ used as the base to track the state of a turn-based combat system. Since
|
|||
Scripts can also operate on a timer they can also update themselves regularly
|
||||
to perform various actions.
|
||||
- They can act as data stores for storing game data persistently in the database
|
||||
(thanks to its ability to have [Attributes](Attributes)).
|
||||
(thanks to its ability to have [Attributes](./Attributes)).
|
||||
- They can be used as OOC stores for sharing data between groups of objects, for
|
||||
example for tracking the turns in a turn-based combat system or barter exchange.
|
||||
|
||||
Scripts are [Typeclassed](Typeclasses) entities and are manipulated in a similar
|
||||
Scripts are [Typeclassed](./Typeclasses) entities and are manipulated in a similar
|
||||
way to how it works for other such Evennia entities:
|
||||
|
||||
```python
|
||||
|
|
@ -41,7 +41,7 @@ list_of_myscript = evennia.search_script("myscript")
|
|||
## Defining new Scripts
|
||||
|
||||
A Script is defined as a class and is created in the same way as other
|
||||
[typeclassed](Typeclasses) entities. The class has several properties
|
||||
[typeclassed](./Typeclasses) entities. The class has several properties
|
||||
to control the timer-component of the scripts. These are all _optional_ -
|
||||
leaving them out will just create a Script with no timer components (useful to act as
|
||||
a database store or to hold a persistent game system, for example).
|
||||
|
|
@ -101,7 +101,7 @@ If we put this script on a room, it will randomly report some weather
|
|||
to everyone in the room every 5 minutes.
|
||||
|
||||
To activate it, just add it to the script handler (`scripts`) on an
|
||||
[Room](Objects). That object becomes `self.obj` in the example above. Here we
|
||||
[Room](./Objects). That object becomes `self.obj` in the example above. Here we
|
||||
put it on a room called `myroom`:
|
||||
|
||||
```
|
||||
|
|
@ -140,7 +140,7 @@ command in-game.
|
|||
|
||||
## Properties and functions defined on Scripts
|
||||
|
||||
A Script has all the properties of a typeclassed object, such as `db` and `ndb`(see [Typeclasses](Typeclasses)). Setting `key` is useful in order to manage scripts (delete them by name etc). These are usually set up in the Script's typeclass, but can also be assigned on the fly as keyword arguments to `evennia.create_script`.
|
||||
A Script has all the properties of a typeclassed object, such as `db` and `ndb`(see [Typeclasses](./Typeclasses)). Setting `key` is useful in order to manage scripts (delete them by name etc). These are usually set up in the Script's typeclass, but can also be assigned on the fly as keyword arguments to `evennia.create_script`.
|
||||
|
||||
- `desc` - an optional description of the script's function. Seen in script listings.
|
||||
- `interval` - how often the script should run. If `interval == 0` (default), this script has no timing component, will not repeat and will exist forever. This is useful for Scripts used for storage or acting as bases for various non-time dependent game systems.
|
||||
|
|
@ -150,7 +150,7 @@ A Script has all the properties of a typeclassed object, such as `db` and `ndb`(
|
|||
|
||||
There is one special property:
|
||||
|
||||
- `obj` - the [Object](Objects) 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)` or give `myobj` as an argument to the `utils.create.create_script` function, the `obj` property will be set to `myobj` for you.
|
||||
- `obj` - the [Object](./Objects) 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)` or give `myobj` as an argument to the `utils.create.create_script` function, 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
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ Finally:
|
|||
Now the only ports open will be your administrative ssh port (whichever you chose), and Evennia on 4000-4001.
|
||||
|
||||
### Use an external webserver
|
||||
Though not officially supported, there are some benefits to [deploying a webserver](Apache-Config) to handle/proxy traffic to your Evennia instance.
|
||||
Though not officially supported, there are some benefits to [deploying a webserver](./Apache-Config) to handle/proxy traffic to your Evennia instance.
|
||||
|
||||
For example, Evennia's game engine and webservice are tightly integrated. If you bring your game down for maintenance (or if it simply crashes) your website will go down with it. In these cases a standalone webserver can still be used to display a maintenance page or otherwise communicate to your users the reason for the downtime, instead of disappearing off the face of the earth and returning opaque `SERVER NOT FOUND` error messages.
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ Evennia runs out of the box without any changes to its settings. But there are s
|
|||
|
||||
## Settings file
|
||||
|
||||
The "Settings" file referenced throughout the documentation is the file `mygame/server/conf/settings.py`. This is automatically created on the first run of `evennia --init` (see the [Getting Started](Getting-Started) page).
|
||||
The "Settings" file referenced throughout the documentation is the file `mygame/server/conf/settings.py`. This is automatically created on the first run of `evennia --init` (see the [Getting Started](./Getting-Started) page).
|
||||
|
||||
Your new `settings.py` is relatively bare out of the box. Evennia's core settings file is actually [evennia/settings_default.py](https://github.com/evennia/evennia/blob/master/evennia/settings_default.py) and is considerably more extensive (it is also heavily documented so you should refer to this file directly for the available settings).
|
||||
|
||||
|
|
@ -38,12 +38,12 @@ Apart from the main `settings.py` file,
|
|||
- `at_initial_setup.py` - this allows you to add a custom startup method to be called (only) the very first time Evennia starts (at the same time as user #1 and Limbo is created). It can be made to start your own global scripts or set up other system/world-related things your game needs to have running from the start.
|
||||
- `at_server_startstop.py` - this module contains two functions that Evennia will call every time the Server starts and stops respectively - this includes stopping due to reloading and resetting as well as shutting down completely. It's a useful place to put custom startup code for handlers and other things that must run in your game but which has no database persistence.
|
||||
- `connection_screens.py` - all global string variables in this module are interpreted by Evennia as a greeting screen to show when an Account first connects. If more than one string variable is present in the module a random one will be picked.
|
||||
- `inlinefuncs.py` - this is where you can define custom [Inline functions](TextTags#inlinefuncs).
|
||||
- `inputfuncs.py` - this is where you define custom [Input functions](Inputfuncs) to handle data from the client.
|
||||
- `lockfuncs.py` - this is one of many possible modules to hold your own "safe" *lock functions* to make available to Evennia's [Locks](Locks).
|
||||
- `inlinefuncs.py` - this is where you can define custom [Inline functions](./TextTags#inlinefuncs).
|
||||
- `inputfuncs.py` - this is where you define custom [Input functions](./Inputfuncs) to handle data from the client.
|
||||
- `lockfuncs.py` - this is one of many possible modules to hold your own "safe" *lock functions* to make available to Evennia's [Locks](./Locks).
|
||||
- `mssp.py` - this holds meta information about your game. It is used by MUD search engines (which you often have to register with) in order to display what kind of game you are running along with
|
||||
statistics such as number of online accounts and online status.
|
||||
- `oobfuncs.py` - in here you can define custom [OOB functions](OOB).
|
||||
- `oobfuncs.py` - in here you can define custom [OOB functions](./OOB).
|
||||
- `portal_services_plugin.py` - this allows for adding your own custom services/protocols to the Portal. It must define one particular function that will be called by Evennia at startup. There can be any number of service plugin modules, all will be imported and used if defined. More info can be found [here](http://code.google.com/p/evennia/wiki/SessionProtocols#Adding_custom_Protocols).
|
||||
- `server_services_plugin.py` - this is equivalent to the previous one, but used for adding new services to the Server instead. More info can be found [here](http://code.google.com/p/evennia/wiki/SessionProtocols#Adding_custom_Protocols).
|
||||
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@
|
|||
|
||||
An Evennia *Session* represents one single established connection to the server. Depending on the Evennia session, it is possible for a person to connect multiple times, for example using different clients in multiple windows. Each such connection is represented by a session object.
|
||||
|
||||
A session object has its own [cmdset](Command-Sets), usually the "unloggedin" cmdset. This is what is used to show the login screen and to handle commands to create a new account (or [Account](Accounts) in evennia lingo) read initial help and to log into the game with an existing account. A session object can either be "logged in" or not. Logged in means that the user has authenticated. When this happens the session is associated with an Account object (which is what holds account-centric stuff). The account can then in turn puppet any number of objects/characters.
|
||||
A session object has its own [cmdset](./Command-Sets), usually the "unloggedin" cmdset. This is what is used to show the login screen and to handle commands to create a new account (or [Account](./Accounts) in evennia lingo) read initial help and to log into the game with an existing account. A session object can either be "logged in" or not. Logged in means that the user has authenticated. When this happens the session is associated with an Account object (which is what holds account-centric stuff). The account can then in turn puppet any number of objects/characters.
|
||||
|
||||
> Warning: A Session is not *persistent* - it is not a [Typeclass](Typeclasses) and has no connection to the database. The Session will go away when a user disconnects and you will lose any custom data on it if the server reloads. The `.db` handler on Sessions is there to present a uniform API (so you can assume `.db` exists even if you don't know if you receive an Object or a Session), but this is just an alias to `.ndb`. So don't store any data on Sessions that you can't afford to lose in a reload. You have been warned.
|
||||
> Warning: A Session is not *persistent* - it is not a [Typeclass](./Typeclasses) and has no connection to the database. The Session will go away when a user disconnects and you will lose any custom data on it if the server reloads. The `.db` handler on Sessions is there to present a uniform API (so you can assume `.db` exists even if you don't know if you receive an Object or a Session), but this is just an alias to `.ndb`. So don't store any data on Sessions that you can't afford to lose in a reload. You have been warned.
|
||||
|
||||
## Properties on Sessions
|
||||
|
||||
|
|
@ -14,11 +14,11 @@ Here are some important properties available on (Server-)Sessions
|
|||
- `sessid` - The unique session-id. This is an integer starting from 1.
|
||||
- `address` - The connected client's address. Different protocols give different information here.
|
||||
- `logged_in` - `True` if the user authenticated to this session.
|
||||
- `account` - The [Account](Accounts) this Session is attached to. If not logged in yet, this is `None`.
|
||||
- `puppet` - The [Character/Object](Objects) currently puppeted by this Account/Session combo. If not logged in or in OOC mode, this is `None`.
|
||||
- `ndb` - The [Non-persistent Attribute](Attributes) handler.
|
||||
- `account` - The [Account](./Accounts) this Session is attached to. If not logged in yet, this is `None`.
|
||||
- `puppet` - The [Character/Object](./Objects) currently puppeted by this Account/Session combo. If not logged in or in OOC mode, this is `None`.
|
||||
- `ndb` - The [Non-persistent Attribute](./Attributes) handler.
|
||||
- `db` - As noted above, Sessions don't have regular Attributes. This is an alias to `ndb`.
|
||||
- `cmdset` - The Session's [CmdSetHandler](Command-Sets)
|
||||
- `cmdset` - The Session's [CmdSetHandler](./Command-Sets)
|
||||
|
||||
Session statistics are mainly used internally by Evennia.
|
||||
|
||||
|
|
@ -51,7 +51,7 @@ On the other hand, if you call the `msg()` message on a puppeted object, like `c
|
|||
Finally, there is a wrapper for `msg()` on all command classes: `command.msg()`. This will transparently detect which session was triggering the command (if any) and redirects to that session (this is most often what you want). If you are having trouble redirecting to a given session, `command.msg()` is often the safest bet.
|
||||
|
||||
You can get the `session` in two main ways:
|
||||
* [Accounts](Accounts) and [Objects](Objects) (including Characters) have a `sessions` property. This is a *handler* that tracks all Sessions attached to or puppeting them. Use e.g. `accounts.sessions.get()` to get a list of Sessions attached to that entity.
|
||||
* [Accounts](./Accounts) and [Objects](./Objects) (including Characters) have a `sessions` property. This is a *handler* that tracks all Sessions attached to or puppeting them. Use e.g. `accounts.sessions.get()` to get a list of Sessions attached to that entity.
|
||||
* A Command instance has a `session` property that always points back to the Session that triggered it (it's always a single one). It will be `None` if no session is involved, like when a mob or script triggers the Command.
|
||||
|
||||
## Customizing the Session object
|
||||
|
|
@ -70,11 +70,11 @@ changes carefully.
|
|||
|
||||
*Note: This is considered an advanced topic. You don't need to know this on a first read-through.*
|
||||
|
||||
Evennia is split into two parts, the [Portal and the Server](Portal-And-Server). Each side tracks its own Sessions, syncing them to each other.
|
||||
Evennia is split into two parts, the [Portal and the Server](./Portal-And-Server). Each side tracks its own Sessions, syncing them to each other.
|
||||
|
||||
The "Session" we normally refer to is actually the `ServerSession`. Its counter-part on the Portal side is the `PortalSession`. Whereas the server sessions deal with game states, the portal session deals with details of the connection-protocol itself. The two are also acting as backups of critical data such as when the server reboots.
|
||||
|
||||
New Account connections are listened for and handled by the Portal using the [protocols](Portal-And-Server) it understands (such as telnet, ssh, webclient etc). When a new connection is established, a `PortalSession` 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
|
||||
New Account connections are listened for and handled by the Portal using the [protocols](./Portal-And-Server) it understands (such as telnet, ssh, webclient etc). When a new connection is established, a `PortalSession` 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 from the Portal, through the AMP connection, to the Server, which is now informed a new connection has been established. On the Server side, a `ServerSession` object is created to represent this. There is only one type of `ServerSession`; It looks the same regardless of how the Account connects.
|
||||
|
|
@ -89,7 +89,7 @@ During certain situations, the portal- and server-side sessions are
|
|||
|
||||
## Sessionhandlers
|
||||
|
||||
Both the Portal and Server each have a *sessionhandler* to manage the connections. These handlers are global entities 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](Custom-Protocols) for more info
|
||||
Both the Portal and Server each have a *sessionhandler* to manage the connections. These handlers are global entities 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](./Custom-Protocols) for more info
|
||||
on building new protocols.
|
||||
|
||||
To get all Sessions in the game (i.e. all currently connected clients), you access the server-side Session handler, which you get by
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ be extracted from the `**kwargs` dict in the signal handler.
|
|||
used way for users to themselves create accounts during login. It passes and extra kwarg `ip` with
|
||||
the client IP of the connecting account.
|
||||
- `SIGNAL_ACCOUNT_POST_LOGIN` - this will always fire when the account has authenticated. Sends
|
||||
extra kwarg `session` with the new [Session](Sessions) object involved.
|
||||
extra kwarg `session` with the new [Session](./Sessions) object involved.
|
||||
- `SIGNAL_ACCCOUNT_POST_FIRST_LOGIN` - this fires just before `SIGNAL_ACCOUNT_POST_LOGIN` but only if
|
||||
this is the *first* connection done (that is, if there are no previous sessions connected). Also
|
||||
passes the `session` along as a kwarg.
|
||||
|
|
|
|||
|
|
@ -90,5 +90,5 @@ Adding advanced and flexible building commands to your game is easy and will pro
|
|||
satisfy most creative builders. However, if you really, *really* want to offer online coding, there
|
||||
is of course nothing stopping you from adding that to Evennia, no matter our recommendations. You
|
||||
could even re-implement MUX' softcode in Python should you be very ambitious. The
|
||||
[in-game-python](Dialogues-in-events) is an optional
|
||||
[in-game-python](./Dialogues-in-events) is an optional
|
||||
pseudo-softcode plugin aimed at developers wanting to script their game from inside it.
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
|
||||
The *spawner* is a system for defining and creating individual objects from a base template called a
|
||||
*prototype*. It is only designed for use with in-game [Objects](Objects), not any other type of
|
||||
*prototype*. It is only designed for use with in-game [Objects](./Objects), not any other type of
|
||||
entity.
|
||||
|
||||
The normal way to create a custom object in Evennia is to make a [Typeclass](Typeclasses). If you
|
||||
The normal way to create a custom object in Evennia is to make a [Typeclass](./Typeclasses). If you
|
||||
haven't read up on Typeclasses yet, think of them as normal Python classes that save to the database
|
||||
behind the scenes. Say you wanted to create a "Goblin" enemy. A common way to do this would be to
|
||||
first create a `Mobile` typeclass that holds everything common to mobiles in the game, like generic
|
||||
|
|
@ -61,7 +61,7 @@ If you wanted to load it into the spawner in-game you could just put all on one
|
|||
> Note that the prototype dict as given on the command line must be a valid Python structure -
|
||||
so you need to put quotes around strings etc. For security reasons, a dict inserted from-in game cannot have any
|
||||
other advanced Python functionality, such as executable code, `lambda` etc. If builders are supposed
|
||||
to be able to use such features, you need to offer them through [$protfuncs](Spawner-and-Prototypes#protfuncs), embedded runnable functions that you have full control to check and vet before running.
|
||||
to be able to use such features, you need to offer them through [$protfuncs](./Spawner-and-Prototypes#protfuncs), embedded runnable functions that you have full control to check and vet before running.
|
||||
|
||||
### Prototype keys
|
||||
|
||||
|
|
@ -92,11 +92,11 @@ The remaining keys determine actual aspects of the objects to spawn from this pr
|
|||
- `home` - a valid `#dbref`. Defaults to `location` or `settings.DEFAULT_HOME` if location does not exist.
|
||||
- `destination` - a valid `#dbref`. Only used by exits.
|
||||
- `permissions` - list of permission strings, like `["Accounts", "may_use_red_door"]`
|
||||
- `locks` - a [lock-string](Locks) like `"edit:all();control:perm(Builder)"`
|
||||
- `locks` - a [lock-string](./Locks) like `"edit:all();control:perm(Builder)"`
|
||||
- `aliases` - list of strings for use as aliases
|
||||
- `tags` - list [Tags](Tags). These are given as tuples `(tag, category, data)`.
|
||||
- `attrs` - list of [Attributes](Attributes). These are given as tuples `(attrname, value, category, lockstring)`
|
||||
- Any other keywords are interpreted as non-category [Attributes](Attributes) and their values. This is
|
||||
- `tags` - list [Tags](./Tags). These are given as tuples `(tag, category, data)`.
|
||||
- `attrs` - list of [Attributes](./Attributes). These are given as tuples `(attrname, value, category, lockstring)`
|
||||
- Any other keywords are interpreted as non-category [Attributes](./Attributes) and their values. This is
|
||||
convenient for simple Attributes - use `attrs` for full control of Attributes.
|
||||
|
||||
Deprecated as of Evennia 0.8:
|
||||
|
|
@ -104,7 +104,7 @@ Deprecated as of Evennia 0.8:
|
|||
- `ndb_<name>` - sets the value of a non-persistent attribute (`"ndb_"` is stripped from the name).
|
||||
This is simply not useful in a prototype and is deprecated.
|
||||
- `exec` - This accepts a code snippet or a list of code snippets to run. This should not be used -
|
||||
use callables or [$protfuncs](Spawner-and-Prototypes#protfuncs) instead (see below).
|
||||
use callables or [$protfuncs](./Spawner-and-Prototypes#protfuncs) instead (see below).
|
||||
|
||||
### Prototype values
|
||||
|
||||
|
|
@ -143,7 +143,7 @@ Finally, the value can be a *prototype function* (*Protfunc*). These look like s
|
|||
"He has $randint(2,5) skulls in a chain around his neck."}
|
||||
```
|
||||
At execution time, the place of the protfunc will be replaced with the result of that protfunc being called (this is always a string). A protfunc works in much the same way as an
|
||||
[InlineFunc](TextTags#inline-functions) - they are actually
|
||||
[InlineFunc](./TextTags#inline-functions) - they are actually
|
||||
parsed using the same parser - except protfuncs are run every time the prototype is used to spawn a new object (whereas an inlinefunc is called when a text is returned to the user).
|
||||
|
||||
Here is how a protfunc is defined (same as an inlinefunc).
|
||||
|
|
@ -202,7 +202,7 @@ A prototype can be defined and stored in two ways, either in the database or as
|
|||
|
||||
### Database prototypes
|
||||
|
||||
Stored as [Scripts](Scripts) in the database. These are sometimes referred to as *database-prototypes* This is the only way for in-game builders to modify and add prototypes. They have the advantage of being easily modifiable and sharable between builders but you need to work with them using in-game tools.
|
||||
Stored as [Scripts](./Scripts) in the database. These are sometimes referred to as *database-prototypes* This is the only way for in-game builders to modify and add prototypes. They have the advantage of being easily modifiable and sharable between builders but you need to work with them using in-game tools.
|
||||
|
||||
### Module-based prototypes
|
||||
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@
|
|||
|
||||
You control Evennia from your game folder (we refer to it as `mygame/` here), using the `evennia`
|
||||
program. If the `evennia` program is not available on the command line you must first install
|
||||
Evennia as described in the [Getting Started](Getting-Started) page.
|
||||
Evennia as described in the [Getting Started](./Getting-Started) page.
|
||||
|
||||
> Hint: If you ever try the `evennia` command and get an error complaining that the command is not available, make sure your [virtualenv](Glossary#virtualenv) is active.
|
||||
> Hint: If you ever try the `evennia` command and get an error complaining that the command is not available, make sure your [virtualenv](./Glossary#virtualenv) is active.
|
||||
|
||||
Below are described the various management options. Run
|
||||
|
||||
|
|
@ -19,7 +19,7 @@ to give you a menu with options.
|
|||
|
||||
## Starting Evennia
|
||||
|
||||
Evennia consists of two components, the Evennia [Server and Portal](Portal-And-Server). Briefly,
|
||||
Evennia consists of two components, the Evennia [Server and Portal](./Portal-And-Server). Briefly,
|
||||
the *Server* is what is running the mud. It handles all game-specific things but doesn'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
|
||||
|
|
@ -65,7 +65,7 @@ reboots. Since they are connected to the *Portal*, their connections are not los
|
|||
|
||||
|
||||
Reloading is as close to a "warm reboot" you can get. It reinitializes all code of Evennia, but
|
||||
doesn't kill "persistent" [Scripts](Scripts). It also calls `at_server_reload()` hooks on all objects so you
|
||||
doesn't kill "persistent" [Scripts](./Scripts). It also calls `at_server_reload()` hooks on all objects so you
|
||||
can save eventual temporary properties you want.
|
||||
|
||||
From in-game the `@reload` command is used. You can also reload the server from outside the game:
|
||||
|
|
|
|||
|
|
@ -3,13 +3,13 @@
|
|||
|
||||
## Introduction
|
||||
|
||||
This tutorial describes the creation of an in-game map display based on a pre-drawn map. It also details how to use the [Batch code processor](Batch-Code-Processor) for advanced building. There is also the [Dynamic in-game map tutorial](Dynamic-In-Game-Map) that works in the opposite direction, by generating a map from an existing grid of rooms.
|
||||
This tutorial describes the creation of an in-game map display based on a pre-drawn map. It also details how to use the [Batch code processor](./Batch-Code-Processor) for advanced building. There is also the [Dynamic in-game map tutorial](./Dynamic-In-Game-Map) that works in the opposite direction, by generating a map from an existing grid of rooms.
|
||||
|
||||
Evennia does not require its rooms to be positioned in a "logical" way. Your exits could be named anything. You could make an exit "west" that leads to a room described to be in the far north. You could have rooms inside one another, exits leading back to the same room or describing spatial geometries impossible in the real world.
|
||||
|
||||
That said, most games *do* organize their rooms in a logical fashion, if nothing else to retain the sanity of their players. And when they do, the game becomes possible to map. This tutorial will give an example of a simple but flexible in-game map system to further help player's to navigate. We will
|
||||
|
||||
To simplify development and error-checking we'll break down the work into bite-size chunks, each building on what came before. For this we'll make extensive use of the [Batch code processor](Batch-Code-Processor), so you may want to familiarize yourself with that.
|
||||
To simplify development and error-checking we'll break down the work into bite-size chunks, each building on what came before. For this we'll make extensive use of the [Batch code processor](./Batch-Code-Processor), so you may want to familiarize yourself with that.
|
||||
|
||||
1. **Planning the map** - Here we'll come up with a small example map to use for the rest of the tutorial.
|
||||
2. **Making a map object** - This will showcase how to make a static in-game "map" object a Character could pick up and look at.
|
||||
|
|
@ -27,7 +27,7 @@ To simplify development and error-checking we'll break down the work into bite-s
|
|||
Exits: north(#8), east(#9), south(#10), west(#11)
|
||||
```
|
||||
|
||||
We will henceforth assume your game folder is name named `mygame` and that you haven't modified the default commands. We will also not be using [Colors](TextTags#colored-text) for our map since they don't show in the documentation wiki.
|
||||
We will henceforth assume your game folder is name named `mygame` and that you haven't modified the default commands. We will also not be using [Colors](./TextTags#colored-text) for our map since they don't show in the documentation wiki.
|
||||
|
||||
## Planning the Map
|
||||
|
||||
|
|
@ -55,11 +55,11 @@ There are many considerations when making a game map depending on the play style
|
|||
|
||||
In this section we will try to create an actual "map" object that an account can pick up and look at.
|
||||
|
||||
Evennia offers a range of [default commands](Default-Command-Help) for [creating objects and rooms in-game](Building-Quickstart). While readily accessible, these commands are made to do very specific, restricted things and will thus not offer as much flexibility to experiment (for an advanced exception see [in-line functions](TextTags#new-inlinefuncs)). Additionally, entering long descriptions and properties over and over in the game client can become tedious; especially when testing and you may want to delete and recreate things over and over.
|
||||
Evennia offers a range of [default commands](./Default-Command-Help) for [creating objects and rooms in-game](./Building-Quickstart). While readily accessible, these commands are made to do very specific, restricted things and will thus not offer as much flexibility to experiment (for an advanced exception see [in-line functions](./TextTags#new-inlinefuncs)). Additionally, entering long descriptions and properties over and over in the game client can become tedious; especially when testing and you may want to delete and recreate things over and over.
|
||||
|
||||
To overcome this, Evennia offers [batch processors](Batch-Processors) that work as input-files created out-of-game. In this tutorial we'll be using the more powerful of the two available batch processors, the [Batch Code Processor ](Batch-Code-Processor), called with the `@batchcode` command. This is a very powerful tool. It allows you to craft Python files to act as blueprints of your entire game world. These files have access to use Evennia's Python API directly. Batchcode allows for easy editing and creation in whatever text editor you prefer, avoiding having to manually build the world line-by-line inside the game.
|
||||
To overcome this, Evennia offers [batch processors](./Batch-Processors) that work as input-files created out-of-game. In this tutorial we'll be using the more powerful of the two available batch processors, the [Batch Code Processor ](./Batch-Code-Processor), called with the `@batchcode` command. This is a very powerful tool. It allows you to craft Python files to act as blueprints of your entire game world. These files have access to use Evennia's Python API directly. Batchcode allows for easy editing and creation in whatever text editor you prefer, avoiding having to manually build the world line-by-line inside the game.
|
||||
|
||||
> Important warning: `@batchcode`'s power is only rivaled by the `@py` command. Batchcode is so powerful it should be reserved only for the [superuser](Building-Permissions). Think carefully before you let others (such as `Developer`- level staff) run `@batchcode` on their own - make sure you are okay with them running *arbitrary Python code* on your server.
|
||||
> Important warning: `@batchcode`'s power is only rivaled by the `@py` command. Batchcode is so powerful it should be reserved only for the [superuser](./Building-Permissions). Think carefully before you let others (such as `Developer`- level staff) run `@batchcode` on their own - make sure you are okay with them running *arbitrary Python code* on your server.
|
||||
|
||||
While a simple example, the map object it serves as good way to try out `@batchcode`. Go to `mygame/world` and create a new file there named `batchcode_map.py`:
|
||||
|
||||
|
|
@ -232,8 +232,7 @@ def return_minimap(x, y, radius = 2):
|
|||
map = ""
|
||||
|
||||
#For each row we need, add the characters we need.
|
||||
for valuey in world_map[y-radius:y+radius+1]:
|
||||
for valuex in valuey[x-radius:x+radius+1]:
|
||||
for valuey in world_map[y-radius:y+radius+1]: for valuex in valuey[x-radius:x+radius+1]:
|
||||
map += valuex
|
||||
map += "\n"
|
||||
|
||||
|
|
@ -334,4 +333,4 @@ Log in to evennia and run `@batchcode batchcode_world` and you'll have a little
|
|||
|
||||
You should now have a mapped little world and a basic understanding of batchcode, EvTable and how easily new game defining features can be added to Evennia.
|
||||
|
||||
You can easily build from this tutorial by expanding the map and creating more rooms to explore. Why not add more features to your game by trying other tutorials: [Add weather to your world](Weather-Tutorial), [fill your world with NPC's](Tutorial-Aggressive-NPCs) or [implement a combat system](Turn-based-Combat-System).
|
||||
You can easily build from this tutorial by expanding the map and creating more rooms to explore. Why not add more features to your game by trying other tutorials: [Add weather to your world](./Weather-Tutorial), [fill your world with NPC's](./Tutorial-Aggressive-NPCs) or [implement a combat system](./Turn-based-Combat-System).
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@
|
|||
|
||||
A common task of a game designer is to organize and find groups of objects and do operations on them. A classic example is to have a weather script affect all "outside" rooms. Another would be for a player casting a magic spell that affects every location "in the dungeon", but not those "outside". Another would be to quickly find everyone joined with a particular guild or everyone currently dead.
|
||||
|
||||
*Tags* are short text labels that you attach to objects so as to easily be able to retrieve and group them. An Evennia entity can be tagged with any number of Tags. On the database side, Tag entities are *shared* between all objects with that tag. This makes them very efficient but also fundamentally different from [Attributes](Attributes), each of which always belongs to one *single* object.
|
||||
*Tags* are short text labels that you attach to objects so as to easily be able to retrieve and group them. An Evennia entity can be tagged with any number of Tags. On the database side, Tag entities are *shared* between all objects with that tag. This makes them very efficient but also fundamentally different from [Attributes](./Attributes), each of which always belongs to one *single* object.
|
||||
|
||||
In Evennia, Tags are technically also used to implement `Aliases` (alternative names for objects) and `Permissions` (simple strings for [Locks](Locks) to check for).
|
||||
In Evennia, Tags are technically also used to implement `Aliases` (alternative names for objects) and `Permissions` (simple strings for [Locks](./Locks) to check for).
|
||||
|
||||
|
||||
## Properties of Tags (and Aliases and Permissions)
|
||||
|
|
@ -14,7 +14,7 @@ Tags are *unique*. This means that there is only ever one Tag object with a give
|
|||
|
||||
> Not specifying a category (default) gives the tag a category of `None`, which is also considered a unique key + category combination.
|
||||
|
||||
When Tags are assigned to game entities, these entities are actually sharing the same Tag. This means that Tags are not suitable for storing information about a single object - use an [Attribute](Attributes) for this instead. Tags are a lot more limited than Attributes but this also makes them very quick to lookup in the database - this is the whole point.
|
||||
When Tags are assigned to game entities, these entities are actually sharing the same Tag. This means that Tags are not suitable for storing information about a single object - use an [Attribute](./Attributes) for this instead. Tags are a lot more limited than Attributes but this also makes them very quick to lookup in the database - this is the whole point.
|
||||
|
||||
Tags have the following properties, stored in the database:
|
||||
|
||||
|
|
@ -28,7 +28,7 @@ There are also two special properties. These should usually not need to be chang
|
|||
|
||||
## Adding/Removing Tags
|
||||
|
||||
You can tag any *typeclassed* object, namely [Objects](Objects), [Accounts](Accounts), [Scripts](Scripts) and [Channels](Communications). General tags are added by the *Taghandler*. The tag handler is accessed as a property `tags` on the relevant entity:
|
||||
You can tag any *typeclassed* object, namely [Objects](./Objects), [Accounts](./Accounts), [Scripts](./Scripts) and [Channels](./Communications). General tags are added by the *Taghandler*. The tag handler is accessed as a property `tags` on the relevant entity:
|
||||
|
||||
```python
|
||||
mychair.tags.add("furniture")
|
||||
|
|
@ -100,7 +100,7 @@ objs = evennia.search_tag(category="bar")
|
|||
|
||||
|
||||
|
||||
There is also an in-game command that deals with assigning and using ([Object-](Objects)) tags:
|
||||
There is also an in-game command that deals with assigning and using ([Object-](./Objects)) tags:
|
||||
|
||||
@tag/search furniture
|
||||
|
||||
|
|
@ -123,4 +123,4 @@ and so on. Similarly to how `@tag` works in-game, there is also the `@perm` comm
|
|||
Generally, tags are enough on their own for grouping objects. Having no tag `category` is perfectly fine and the normal operation. Simply adding a new Tag for grouping objects is often better than making a new category. So think hard before deciding you really need to categorize your Tags.
|
||||
|
||||
That said, tag categories can be useful if you build some game system that uses tags. You can then use tag categories to make sure to separate tags created with this system from any other tags created elsewhere. You can then supply custom search methods that *only* find objects tagged with tags of that category. An example of this
|
||||
is found in the [Zone tutorial](Zones).
|
||||
is found in the [Zone tutorial](./Zones).
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
This documentation details the various text tags supported by Evennia, namely *colours*, *command links* and *inline functions*.
|
||||
|
||||
There is also an [Understanding Color Tags](Understanding-Color-Tags) tutorial which expands on the use of ANSI color tags and the pitfalls of mixing ANSI and Xterms256 color tags in the same context.
|
||||
There is also an [Understanding Color Tags](./Understanding-Color-Tags) tutorial which expands on the use of ANSI color tags and the pitfalls of mixing ANSI and Xterms256 color tags in the same context.
|
||||
|
||||
## Coloured text
|
||||
|
||||
|
|
@ -13,13 +13,13 @@ Color can be a very useful tool for your game. It can be used to increase readab
|
|||
|
||||
Remember however that, with the exception of the webclient, you generally don't control the client used to connect to the game. There is, for example, one special tag meaning "yellow". But exactly *which* hue of yellow is actually displayed on the user's screen depends on the settings of their particular mud client. They could even swap the colours around or turn them off altogether if so desired. Some clients don't even support color - 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](Manually-Configuring-Color).
|
||||
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](./Manually-Configuring-Color).
|
||||
|
||||
To see which colours your client support, use the default `@color` command. This will list all available colours for ANSI and Xterm256 along with the codes you use for them. You can find a list of all the parsed `ANSI`-colour codes in `evennia/utils/ansi.py`.
|
||||
|
||||
### ANSI colours
|
||||
|
||||
Evennia supports the `ANSI` standard for text. This is by far the most supported MUD-color standard, available in all but the most ancient mud clients. The ANSI colours are **r**ed, **g**reen, **y**ellow, **b**lue, **m**agenta, **c**yan, **w**hite and black. They are abbreviated by their first letter except for black which is abbreviated with the letter **x**. In ANSI there are "bright" and "normal" (darker) versions of each color, adding up to a total of 16 colours to use for foreground text. There are also 8 "background" colours. These have no bright alternative in ANSI (but Evennia uses the [Xterm256](TextTags#xterm256-colours) extension behind the scenes to offer them anyway).
|
||||
Evennia supports the `ANSI` standard for text. This is by far the most supported MUD-color standard, available in all but the most ancient mud clients. The ANSI colours are **r**ed, **g**reen, **y**ellow, **b**lue, **m**agenta, **c**yan, **w**hite and black. They are abbreviated by their first letter except for black which is abbreviated with the letter **x**. In ANSI there are "bright" and "normal" (darker) versions of each color, adding up to a total of 16 colours to use for foreground text. There are also 8 "background" colours. These have no bright alternative in ANSI (but Evennia uses the [Xterm256](./TextTags#xterm256-colours) extension behind the scenes to offer them anyway).
|
||||
|
||||
To colour your text you put special tags in it. Evennia will parse these and convert them to the correct markup for the client used. If the user's client/console/display supports ANSI colour, they will see the text in the specified colour, otherwise the tags will be stripped (uncolored text). This works also for non-terminal clients, such as the webclient. For the webclient, Evennia will translate the codes to HTML RGB colors.
|
||||
|
||||
|
|
@ -40,7 +40,7 @@ Here is an example of the tags in action:
|
|||
- `|h` is used to make any following foreground ANSI colors bright (it has no effect on Xterm colors). This is only relevant to use with `|!` type tags and will be valid until the next `|n`, `|H` or normal (upper-case) `|#` tag. This tag will never affect background colors, those have to be set bright/normal explicitly. Technically, `|h|!G` is identical to `|g`.
|
||||
- `|H` negates the effects `|h` and returns all ANSI foreground colors (`|!` and `|` types) to 'normal' intensity. It has no effect on background and Xterm colors.
|
||||
|
||||
> Note: The ANSI standard does not actually support bright backgrounds like `|[r` - the standard only supports "normal" intensity backgrounds. To get around this Evennia instead implements these as [Xterm256 colours](TextTags#xterm256-colours) behind the scenes. If the client does not support Xterm256 the ANSI colors will be used instead and there will be no visible difference between using upper- and lower-case background tags.
|
||||
> Note: The ANSI standard does not actually support bright backgrounds like `|[r` - the standard only supports "normal" intensity backgrounds. To get around this Evennia instead implements these as [Xterm256 colours](./TextTags#xterm256-colours) behind the scenes. If the client does not support Xterm256 the ANSI colors will be used instead and there will be no visible difference between using upper- and lower-case background tags.
|
||||
|
||||
If you want to display an ANSI marker as output text (without having any effect), you need to escape it by preceding its `|` with another `|`:
|
||||
|
||||
|
|
@ -91,7 +91,7 @@ The `|*` tag (inverse video) is an old ANSI standard and should usually not be u
|
|||
```
|
||||
|*reversed text |!R now BG is red.
|
||||
```
|
||||
For a detailed explanation of these caveats, see the [Understanding Color Tags](Understanding-Color-Tags) tutorial. But most of the time you might be better off to simply avoid `|*` and mark your text manually instead.
|
||||
For a detailed explanation of these caveats, see the [Understanding Color Tags](./Understanding-Color-Tags) tutorial. But most of the time you might be better off to simply avoid `|*` and mark your text manually instead.
|
||||
|
||||
### Xterm256 Colours
|
||||
|
||||
|
|
@ -172,7 +172,7 @@ def funcname(*args, **kwargs):
|
|||
|
||||
where `*args` denotes all the arguments this function will accept as an `$inlinefunc`. The inline function is expected to clean arguments and check that they are valid. If needed arguments are not given, default values should be used. The function should always return a string (even if it's empty). An inlinefunc should never cause a traceback regardless of the input (but it could log errors if desired).
|
||||
|
||||
Note that whereas the function should accept `**kwargs`, keyword inputs are *not* usable in the call to the inlinefunction. The `kwargs` part is instead intended for Evennia to be able to supply extra information. Currently Evennia sends a single keyword to every inline function and that is `session`, which holds the [serversession](Sessions) this text is targeted at. Through the session object, a lot of dynamic possibilities are opened up for your inline functions.
|
||||
Note that whereas the function should accept `**kwargs`, keyword inputs are *not* usable in the call to the inlinefunction. The `kwargs` part is instead intended for Evennia to be able to supply extra information. Currently Evennia sends a single keyword to every inline function and that is `session`, which holds the [serversession](./Sessions) this text is targeted at. Through the session object, a lot of dynamic possibilities are opened up for your inline functions.
|
||||
|
||||
The `settings.INLINEFUNC_MODULES` configuration option is a list that decides which modules should be parsed for inline function definitions. This will include `mygame/server/conf/inlinefuncs.py` but more could be added. The list is read from left to right so if you want to overload default functions you just have to put your custom module-paths later in the list and name your functions the same as default ones.
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ One way to implement a dynamic MUD is by using "tickers", also known as "heartbe
|
|||
|
||||
Tickers are very common or even unavoidable in other mud code bases. Certain code bases are even hard-coded to rely on the concept of the global 'tick'. Evennia has no such notion - the decision to use tickers is very much up to the need of your game and which requirements you have. The "ticker recipe" is just one way of cranking the wheels.
|
||||
|
||||
The most fine-grained way to manage the flow of time is of course to use [Scripts](Scripts). Many types of operations (weather being the classic example) are however done on multiple objects in the same way at regular intervals, and for this, storing separate Scripts on each object is inefficient. The way to do this is to use a ticker with a "subscription model" - let objects sign up to be triggered at the same interval, unsubscribing when the updating is no longer desired.
|
||||
The most fine-grained way to manage the flow of time is of course to use [Scripts](./Scripts). Many types of operations (weather being the classic example) are however done on multiple objects in the same way at regular intervals, and for this, storing separate Scripts on each object is inefficient. The way to do this is to use a ticker with a "subscription model" - let objects sign up to be triggered at the same interval, unsubscribing when the updating is no longer desired.
|
||||
|
||||
Evennia offers an optimized implementation of the subscription model - the *TickerHandler*. This is a singleton global handler reachable from `evennia.TICKER_HANDLER`. You can assign any *callable* (a function or, more commonly, a method on a database object) to this handler. The TickerHandler will then call this callable at an interval you specify, and with the arguments you supply when adding it. This continues until the callable un-subscribes from the ticker. The handler survives a reboot and is highly optimized in resource usage.
|
||||
|
||||
|
|
@ -73,11 +73,11 @@ If you add a ticker with exactly the same combination of callback, interval and
|
|||
|
||||
The `callable` can be on any form as long as it accepts the arguments you give to send to it in `TickerHandler.add`.
|
||||
|
||||
> Note that everything you supply to the TickerHandler will need to be pickled at some point to be saved into the database. Most of the time the handler will correctly store things like database objects, but the same restrictions as for [Attributes](Attributes) apply to what the TickerHandler may store.
|
||||
> Note that everything you supply to the TickerHandler will need to be pickled at some point to be saved into the database. Most of the time the handler will correctly store things like database objects, but the same restrictions as for [Attributes](./Attributes) apply to what the TickerHandler may store.
|
||||
|
||||
When testing, you can stop all tickers in the entire game with `tickerhandler.clear()`. You can also view the currently subscribed objects with `tickerhandler.all()`.
|
||||
|
||||
See the [Weather Tutorial](Weather-Tutorial) for an example of using the TickerHandler.
|
||||
See the [Weather Tutorial](./Weather-Tutorial) for an example of using the TickerHandler.
|
||||
|
||||
### When *not* to use TickerHandler
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ Most MUDs will use some sort of combat system. There are several main variations
|
|||
- _Twitch_ - This is the traditional MUD hack&slash style combat. In a twitch system there is often no difference between your normal "move-around-and-explore mode" and the "combat mode". You enter an attack command and the system will calculate if the attack hits and how much damage was caused. Normally attack commands have some sort of timeout or notion of recovery/balance to reduce the advantage of spamming or client scripting. Whereas the simplest systems just means entering `kill <target>` over and over, more sophisticated twitch systems include anything from defensive stances to tactical positioning.
|
||||
- _Turn-based_ - a turn based system means that the system pauses to make sure all combatants can choose their actions before continuing. In some systems, such entered actions happen immediately (like twitch-based) whereas in others the resolution happens simultaneously at the end of the turn. The disadvantage of a turn-based system is that the game must switch to a "combat mode" and one also needs to take special care of how to handle new combatants and the passage of time. The advantage is that success is not dependent on typing speed or of setting up quick client macros. This potentially allows for emoting as part of combat which is an advantage for roleplay-heavy games.
|
||||
|
||||
To implement a freeform combat system all you need is a dice roller and a roleplaying rulebook. See [contrib/dice.py](https://github.com/evennia/evennia/blob/master/evennia/contrib/dice.py) for an example dice roller. To implement at twitch-based system you basically need a few combat [commands](Commands), possibly ones with a [cooldown](Command-Cooldown). You also need a [game rule module](Implementing-a-game-rule-system) that makes use of it. We will focus on the turn-based variety here.
|
||||
To implement a freeform combat system all you need is a dice roller and a roleplaying rulebook. See [contrib/dice.py](https://github.com/evennia/evennia/blob/master/evennia/contrib/dice.py) for an example dice roller. To implement at twitch-based system you basically need a few combat [commands](./Commands), possibly ones with a [cooldown](./Command-Cooldown). You also need a [game rule module](./Implementing-a-game-rule-system) that makes use of it. We will focus on the turn-based variety here.
|
||||
|
||||
## Tutorial overview
|
||||
|
||||
|
|
@ -28,18 +28,18 @@ This tutorial will implement the slightly more complex turn-based combat system.
|
|||
|
||||
For creating the combat system we will need the following components:
|
||||
|
||||
- A combat handler. This is the main mechanic of the system. This is a [Script](Scripts) object created for each combat. It is not assigned to a specific object but is shared by the combating characters and handles all the combat information. Since Scripts are database entities it also means that the combat will not be affected by a server reload.
|
||||
- A combat [command set](Command-Sets) with the relevant commands needed for combat, such as the various attack/defend options and the `flee/disengage` command to leave the combat mode.
|
||||
- A rule resolution system. The basics of making such a module is described in the [rule system tutorial](Implementing-a-game-rule-system). We will only sketch such a module here for our end-turn combat resolution.
|
||||
- An `attack` [command](Commands) for initiating the combat mode. This is added to the default command set. It will create the combat handler and add the character(s) to it. It will also assign the combat command set to the characters.
|
||||
- A combat handler. This is the main mechanic of the system. This is a [Script](./Scripts) object created for each combat. It is not assigned to a specific object but is shared by the combating characters and handles all the combat information. Since Scripts are database entities it also means that the combat will not be affected by a server reload.
|
||||
- A combat [command set](./Command-Sets) with the relevant commands needed for combat, such as the various attack/defend options and the `flee/disengage` command to leave the combat mode.
|
||||
- A rule resolution system. The basics of making such a module is described in the [rule system tutorial](./Implementing-a-game-rule-system). We will only sketch such a module here for our end-turn combat resolution.
|
||||
- An `attack` [command](./Commands) for initiating the combat mode. This is added to the default command set. It will create the combat handler and add the character(s) to it. It will also assign the combat command set to the characters.
|
||||
|
||||
## The combat handler
|
||||
|
||||
The _combat handler_ is implemented as a stand-alone [Script](Scripts). This Script is created when the first Character decides to attack another and is deleted when no one is fighting any more. Each handler represents one instance of combat and one combat only. Each instance of combat can hold any number of characters but each character can only be part of one combat at a time (a player would need to disengage from the first combat before they could join another).
|
||||
The _combat handler_ is implemented as a stand-alone [Script](./Scripts). This Script is created when the first Character decides to attack another and is deleted when no one is fighting any more. Each handler represents one instance of combat and one combat only. Each instance of combat can hold any number of characters but each character can only be part of one combat at a time (a player would need to disengage from the first combat before they could join another).
|
||||
|
||||
The reason we don't store this Script "on" any specific character is because any character may leave the combat at any time. Instead the script holds references to all characters involved in the combat. Vice-versa, all characters holds a back-reference to the current combat handler. While we don't use this very much here this might allow the combat commands on the characters to access and update the combat handler state directly.
|
||||
|
||||
_Note: Another way to implement a combat handler would be to use a normal Python object and handle time-keeping with the [TickerHandler](TickerHandler). This would require either adding custom hook methods on the character or to implement a custom child of the TickerHandler class to track turns. Whereas the TickerHandler is easy to use, a Script offers more power in this case._
|
||||
_Note: Another way to implement a combat handler would be to use a normal Python object and handle time-keeping with the [TickerHandler](./TickerHandler). This would require either adding custom hook methods on the character or to implement a custom child of the TickerHandler class to track turns. Whereas the TickerHandler is easy to use, a Script offers more power in this case._
|
||||
|
||||
Here is a basic combat handler. Assuming our game folder is named `mygame`, we store it in `mygame/typeclasses/combat_handler.py`:
|
||||
|
||||
|
|
@ -284,7 +284,7 @@ class CombatCmdSet(CmdSet):
|
|||
|
||||
## Rules module
|
||||
|
||||
A general way to implement a rule module is found in the [rule system tutorial](Implementing-a-game-rule-system). Proper resolution would likely require us to change our Characters to store things like strength, weapon skills and so on. So for this example we will settle for a very simplistic rock-paper-scissors kind of setup with some randomness thrown in. We will not deal with damage here but just announce the results of each turn. In a real system the Character objects would hold stats to affect their skills, their chosen weapon affect the choices, they would be able to lose health etc.
|
||||
A general way to implement a rule module is found in the [rule system tutorial](./Implementing-a-game-rule-system). Proper resolution would likely require us to change our Characters to store things like strength, weapon skills and so on. So for this example we will settle for a very simplistic rock-paper-scissors kind of setup with some randomness thrown in. We will not deal with damage here but just announce the results of each turn. In a real system the Character objects would hold stats to affect their skills, their chosen weapon affect the choices, they would be able to lose health etc.
|
||||
|
||||
Within each turn, there are "sub-turns", each consisting of one action per character. The actions within each sub-turn happens simultaneously and only once they have all been resolved we move on to the next sub-turn (or end the full turn).
|
||||
|
||||
|
|
@ -424,7 +424,7 @@ class CmdAttack(Command):
|
|||
target.msg("%s attacks you! You are in combat." % self.caller)
|
||||
```
|
||||
|
||||
The `attack` command will not go into the combat cmdset but rather into the default cmdset. See e.g. the [Adding Command Tutorial](Adding-Command-Tutorial) if you are unsure about how to do this.
|
||||
The `attack` command will not go into the combat cmdset but rather into the default cmdset. See e.g. the [Adding Command Tutorial](./Adding-Command-Tutorial) if you are unsure about how to do this.
|
||||
|
||||
## Expanding the example
|
||||
|
||||
|
|
|
|||
|
|
@ -3,14 +3,14 @@
|
|||
|
||||
This tutorial shows the implementation of an NPC object that responds to characters entering their location. In this example the NPC has the option to respond aggressively or not, but any actions could be triggered this way.
|
||||
|
||||
One could imagine using a [Script](Scripts) that is constantly checking for newcomers. This would be highly inefficient (most of the time its check would fail). Instead we handle this on-demand by using a couple of existing object hooks to inform the NPC that a Character has entered.
|
||||
One could imagine using a [Script](./Scripts) that is constantly checking for newcomers. This would be highly inefficient (most of the time its check would fail). Instead we handle this on-demand by using a couple of existing object hooks to inform the NPC that a Character has entered.
|
||||
|
||||
It is assumed that you already know how to create custom room and character typeclasses, please see the [Basic Game tutorial](Tutorial-for-basic-MUSH-like-game) if you haven't already done this.
|
||||
It is assumed that you already know how to create custom room and character typeclasses, please see the [Basic Game tutorial](./Tutorial-for-basic-MUSH-like-game) if you haven't already done this.
|
||||
|
||||
What we will need is the following:
|
||||
|
||||
- An NPC typeclass that can react when someone enters.
|
||||
- A custom [Room](Objects#rooms) typeclass that can tell the NPC that someone entered.
|
||||
- A custom [Room](./Objects#rooms) typeclass that can tell the NPC that someone entered.
|
||||
- We will also tweak our default `Character` typeclass a little.
|
||||
|
||||
To begin with, we need to create an NPC typeclass. Create a new file inside of your typeclasses folder and name it `npcs.py` and then add the following code:
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
This tutorial shows the implementation of an NPC object that responds to characters speaking in their location. In this example the NPC parrots what is said, but any actions could be triggered this way.
|
||||
|
||||
It is assumed that you already know how to create custom room and character typeclasses, please see the [Basic Game tutorial](Tutorial-for-basic-MUSH-like-game) if you haven't already done this.
|
||||
It is assumed that you already know how to create custom room and character typeclasses, please see the [Basic Game tutorial](./Tutorial-for-basic-MUSH-like-game) if you haven't already done this.
|
||||
|
||||
What we will need is simply a new NPC typeclass that can react when someone speaks.
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue