mirror of
https://github.com/evennia/evennia.git
synced 2026-04-04 15:07:16 +02:00
Merge branch 'GulliblePsychologist-argparser' into develop
This commit is contained in:
commit
cc352f7723
38 changed files with 12246 additions and 1728 deletions
382
docs/source/Components/FuncParser.md
Normal file
382
docs/source/Components/FuncParser.md
Normal file
|
|
@ -0,0 +1,382 @@
|
|||
# The Inline Function Parser
|
||||
|
||||
The [FuncParser](api:evennia.utils.funcparser#evennia.utils.funcparser.FuncParser) extracts and executes
|
||||
'inline functions'
|
||||
embedded in a string on the form `$funcname(args, kwargs)`. Under the hood, this will
|
||||
lead to a call to a Python function you control. The inline function call will be replaced by
|
||||
the return from the function.
|
||||
|
||||
```python
|
||||
from evennia.utils.funcparser import FuncParser
|
||||
|
||||
def _power_callable(*args, **kwargs):
|
||||
"""This will be callable as $square(number, power=<num>) in string"""
|
||||
pow = int(kwargs.get('power', 2))
|
||||
return float(args[0]) ** pow
|
||||
|
||||
parser = FuncParser({"pow": _power_callable})
|
||||
|
||||
```
|
||||
Next, just pass a string into the parser, optionally containing `$func(...)` markers:
|
||||
|
||||
```python
|
||||
parser.parse("We have that 4 x 4 x 4 is $pow(4, power=3).")
|
||||
"We have that 4 x 4 x 4 is 64."
|
||||
```
|
||||
|
||||
Normally the return is always converted to a string but you can also get the actual data type from the call:
|
||||
|
||||
```python
|
||||
parser.parse_to_any("$pow(4)")
|
||||
16
|
||||
```
|
||||
|
||||
To show a `$func()` verbatim in your code without parsing it, escape it as either `$$func()` or `\$func()`:
|
||||
|
||||
|
||||
```python
|
||||
parser.parse("This is an escaped $$pow(4) and so is this \$pow(3)")
|
||||
"This is an escaped $pow(4) and so is this $pow(3)"
|
||||
```
|
||||
|
||||
## Uses in default Evennia
|
||||
|
||||
The FuncParser can be applied to any string. Out of the box it's applied in a few situations:
|
||||
|
||||
- _Outgoing messages_. All messages sent from the server is processed through FuncParser and every
|
||||
callable is provided the [Session](./Sessions) of the object receiving the message. This potentially
|
||||
allows a message to be modified on the fly to look different for different recipients.
|
||||
- _Prototype values_. A [Prototype](./Prototypes) dict's values are run through the parser such that every
|
||||
callable gets a reference to the rest of the prototype. In the Prototype ORM, this would allow builders
|
||||
to safely call functions to set non-string values to prototype values, get random values, reference
|
||||
other fields of the prototype, and more.
|
||||
- _Actor-stance in messages to others_. In the
|
||||
[Object.msg_contents](api:evennia.objects.objects#DefaultObject.msg_contents) method,
|
||||
the outgoing string is parsed for special `$You()` and `$conj()` callables to decide if a given recipient
|
||||
should see "You" or the character's name.
|
||||
|
||||
```important::
|
||||
The inline-function parser is not intended as a 'softcode' programming language. It does not
|
||||
have things like loops and conditionals, for example. While you could in principle extend it to
|
||||
do very advanced things and allow builders a lot of power, all-out coding is something
|
||||
Evennia expects you to do in a proper text editor, outside of the game, not from inside it.
|
||||
```
|
||||
|
||||
## Using the FuncParser
|
||||
|
||||
You can apply inline function parsing to any string. The
|
||||
[FuncParser](api:evennia.utils.funcparser.FuncParser) is found in `evennia.utils.funcparser.py`.
|
||||
|
||||
```python
|
||||
from evennia.utils import funcparser
|
||||
|
||||
parser = FuncParser(callables, **default_kwargs)
|
||||
parsed_string = parser.parser(input_string, raise_errors=False,
|
||||
escape=False, strip=False,
|
||||
return_str=True, **reserved_kwargs)
|
||||
|
||||
# callables can also be passed as paths to modules
|
||||
parser = FuncParser(["game.myfuncparser_callables", "game.more_funcparser_callables"])
|
||||
```
|
||||
|
||||
Here, `callables` points to a collection of normal Python functions (see next section) for you to make
|
||||
available to the parser as you parse strings with it. It can either be
|
||||
- A `dict` of `{"functionname": callable, ...}`. This allows you do pick and choose exactly which callables
|
||||
to include and how they should be named. Do you want a callable to be available under more than one name?
|
||||
Just add it multiple times to the dict, with a different key.
|
||||
- A `module` or (more commonly) a `python-path` to a module. This module can define a dict
|
||||
`FUNCPARSER_CALLABLES = {"funcname": callable, ...}` - this will be imported and used like ther `dict` above.
|
||||
If no such variable is defined, _every_ top-level function in the module (whose name doesn't start with
|
||||
an underscore `_`) will be considered a suitable callable. The name of the function will be the `$funcname`
|
||||
by which it can be called.
|
||||
- A `list` of modules/paths. This allows you to pull in modules from many sources for your parsing.
|
||||
|
||||
The other arguments to the parser:
|
||||
|
||||
- `raise_errors` - By default, any errors from a callable will be quietly ignored and the result
|
||||
will be that the failing function call will show verbatim. If `raise_errors` is set,
|
||||
then parsing will stop and whatever exception happened will be raised. It'd be up to you to handle
|
||||
this properly.
|
||||
- `escape` - Returns a string where every `$func(...)` has been escaped as `\$func()`.
|
||||
- `strip` - Remove all `$func(...)` calls from string (as if each returned `''`).
|
||||
- `return_str` - When `True` (default), `parser` always returns a string. If `False`, it may return
|
||||
the return value of a single function call in the string. This is the same as using the `.parse_to_any`
|
||||
method.
|
||||
- The `**default/reserved_keywords` are optional and allow you to pass custom data into _every_ function
|
||||
call. This is great for including things like the current session or config options. Defaults can be
|
||||
replaced if the user gives the same-named kwarg in the string's function call. Reserved kwargs are always passed,
|
||||
ignoring defaults or what the user passed. In addition, the `funcparser` and `raise_errors`
|
||||
reserved kwargs are always passed - the first is a back-reference to the `FuncParser` instance and the second
|
||||
is the `raise_errors` boolean passed into `FuncParser.parse`.
|
||||
|
||||
Here's an example of using the default/reserved keywords:
|
||||
|
||||
```python
|
||||
def _test(*args, **kwargs):
|
||||
# do stuff
|
||||
return something
|
||||
|
||||
parser = funcparser.FuncParser({"test": _test}, mydefault=2)
|
||||
result = parser.parse("$test(foo, bar=4)", myreserved=[1, 2, 3])
|
||||
```
|
||||
Here the callable will be called as
|
||||
|
||||
```python
|
||||
_test('foo', bar='4', mydefault=2, myreserved=[1, 2, 3],
|
||||
funcparser=<FuncParser>, raise_errrors=False)
|
||||
```
|
||||
|
||||
The `mydefault=2` kwarg could be overwritten if we made the call as `$test(mydefault=...)`
|
||||
but `myreserved=[1, 2, 3]` will _always_ be sent as-is and will override a call `$test(myreserved=...)`.
|
||||
The `funcparser`/`raise_errors` kwargs are also always included as reserved kwargs.
|
||||
|
||||
## Defining custom callables
|
||||
|
||||
All callables made available to the parser must have the following signature:
|
||||
|
||||
```python
|
||||
def funcname(*args, **kwargs):
|
||||
# ...
|
||||
return something
|
||||
```
|
||||
|
||||
> The `*args` and `**kwargs` must always be included. If you are unsure how `*args` and `**kwargs` work in Python,
|
||||
> [read about them here](https://www.digitalocean.com/community/tutorials/how-to-use-args-and-kwargs-in-python-3).
|
||||
|
||||
The input from the innermost `$funcname(...)` call in your callable will always be a `str`. Here's
|
||||
an example of an `$toint` function; it converts numbers to integers.
|
||||
|
||||
"There's a $toint(22.0)% chance of survival."
|
||||
|
||||
What will enter the `$toint` callable (as `args[0]`) is the _string_ `"22.0"`. The function is responsible
|
||||
for converting this to a number so that we can convert it to an integer. We must also properly handle invalid
|
||||
inputs (like non-numbers).
|
||||
|
||||
If you want to mark an error, raise `evennia.utils.funcparser.ParsingError`. This stops the entire parsing
|
||||
of the string and may or may not raise the exception depending on what you set `raise_errors` to when you
|
||||
created the parser.
|
||||
|
||||
However, if you _nest_ functions, the return of the innermost function may be something other than
|
||||
a string. Let's introduce the `$eval` function, which evaluates simple expressions using
|
||||
Python's `literal_eval` and/or `simple_eval`.
|
||||
|
||||
"There's a $toint($eval(10 * 2.2))% chance of survival."
|
||||
|
||||
Since the `$eval` is the innermost call, it will get a string as input - the string `"10 * 2.2"`.
|
||||
It evaluates this and returns the `float` `22.0`. This time the outermost `$toint` will be called with
|
||||
this `float` instead of with a string.
|
||||
|
||||
> It's important to safely validate your inputs since users may end up nesting your callables in any order.
|
||||
> See the next section for useful tools to help with this.
|
||||
|
||||
In these examples, the result will be embedded in the larger string, so the result of the entire parsing
|
||||
will be a string:
|
||||
|
||||
```python
|
||||
parser.parse(above_string)
|
||||
"There's a 22% chance of survival."
|
||||
```
|
||||
|
||||
However, if you use the `parse_to_any` (or `parse(..., return_str=True)`) and _don't add any extra string around the outermost function call_,
|
||||
you'll get the return type of the outermost callable back:
|
||||
|
||||
```python
|
||||
parser.parse_to_any("$toint($eval(10 * 2.2)%")
|
||||
"22%"
|
||||
parser.parse_to_any("$toint($eval(10 * 2.2)")
|
||||
22
|
||||
```
|
||||
|
||||
### Safe convertion of inputs
|
||||
|
||||
Since you don't know in which order users may use your callables, they should always check the types
|
||||
of its inputs and convert to the type the callable needs. Note also that when converting from strings,
|
||||
there are limits what inputs you can support. This is because FunctionParser strings are often used by
|
||||
non-developer players/builders and some things (such as complex classes/callables etc) are just not
|
||||
safe/possible to convert from string representation.
|
||||
|
||||
In `evennia.utils.utils` is a helper called
|
||||
[safe_convert_to_types](api:evennia.utils.utils#evennia.utils.utils.safe_convert_to_types). This function
|
||||
automates the conversion of simple data types in a safe way:
|
||||
|
||||
```python
|
||||
from evennia.utils.utils import safe_convert_to_types
|
||||
|
||||
def _process_callable(*args, **kwargs):
|
||||
"""
|
||||
A callable with a lot of custom options
|
||||
|
||||
$process(expression, local, extra=34, extra2=foo)
|
||||
|
||||
"""
|
||||
args, kwargs = safe_convert_to_type(
|
||||
(('py', 'py'), {'extra1': int, 'extra2': str}),
|
||||
*args, **kwargs)
|
||||
|
||||
# args/kwargs should be correct types now
|
||||
|
||||
```
|
||||
|
||||
In other words,
|
||||
|
||||
```python
|
||||
args, kwargs = safe_convert_to_type(
|
||||
(tuple_of_arg_converters, dict_of_kwarg_converters), *args, **kwargs)
|
||||
```
|
||||
|
||||
Each converter should be a callable taking one argument - this will be the arg/kwarg-value to convert. The
|
||||
special converter `"py"` will try to convert a string argument to a Python structure with the help of the
|
||||
following tools (which you may also find useful to experiment with on your own):
|
||||
|
||||
- [ast.literal_eval](https://docs.python.org/3.8/library/ast.html#ast.literal_eval) is an in-built Python
|
||||
function. It
|
||||
_only_ supports strings, bytes, numbers, tuples, lists, dicts, sets, booleans and `None`. That's
|
||||
it - no arithmetic or modifications of data is allowed. This is good for converting individual values and
|
||||
lists/dicts from the input line to real Python objects.
|
||||
- [simpleeval](https://pypi.org/project/simpleeval/) is a third-party tool included with Evennia. This
|
||||
allows for evaluation of simple (and thus safe) expressions. One can operate on numbers and strings
|
||||
with +-/* as well as do simple comparisons like `4 > 3` and more. It does _not_ accept more complex
|
||||
containers like lists/dicts etc, so this and `literal_eval` are complementary to each other.
|
||||
|
||||
```warning::
|
||||
It may be tempting to run use Python's in-built ``eval()`` or ``exec()`` functions as converters since
|
||||
these are able to convert any valid Python source code to Python. NEVER DO THIS unless you really, really
|
||||
know that ONLY developers will ever modify the string going into the callable. The parser is intended
|
||||
for untrusted users (if you were trusted you'd have access to Python already). Letting untrusted users
|
||||
pass strings to ``eval``/``exec`` is a MAJOR security risk. It allows the caller to run arbitrary
|
||||
Python code on your server. This is the path to maliciously deleted hard drives. Just don't do it and
|
||||
sleep better at night.
|
||||
```
|
||||
|
||||
## Default callables
|
||||
|
||||
These are some example callables you can import and add your parser. They are divided into
|
||||
global-level dicts in `evennia.utils.funcparser`. Just import the dict(s) and merge/add one or
|
||||
more to them when you create your `FuncParser` instance to have those callables be available.
|
||||
|
||||
### `evennia.utils.funcparser.FUNCPARSER_CALLABLES`
|
||||
|
||||
These are the 'base' callables.
|
||||
|
||||
- `$eval(expression)` ([code](api:evennia.utils.funcparser#evennia.utils.funcparser.funcparser_callable_eval)) -
|
||||
this uses `literal_eval` and `simple_eval` (see previous section) attemt to convert a string expression
|
||||
to a python object. This handles e.g. lists of literals `[1, 2, 3]` and simple expressions like `"1 + 2"`.
|
||||
- `$toint(number)` ([code](api:evennia.utils.funcparser#evennia.utils.funcparser.funcparser_callable_toint)) -
|
||||
always converts an output to an integer, if possible.
|
||||
- `$add/sub/mult/div(obj1, obj2)` ([code](api:evennia.utils.funcparser#evennia.utils.funcparser.funcparser_callable_add)) -
|
||||
this adds/subtracts/multiplies and divides to elements together. While simple addition could be done with
|
||||
`$eval`, this could for example be used also to add two lists together, which is not possible with `eval`;
|
||||
for example `$add($eval([1,2,3]), $eval([4,5,6])) -> [1, 2, 3, 4, 5, 6]`.
|
||||
- `$round(float, significant)` ([code](api:evennia.utils.funcparser#evennia.utils.funcparser.funcparser_callable_round)) -
|
||||
rounds an input float into the number of provided significant digits. For example `$round(3.54343, 3) -> 3.543`.
|
||||
- `$random([start, [end]])` ([code](api:evennia.utils.funcparser#evennia.utils.funcparser.funcparser_callable_random)) -
|
||||
this works like the Python `random()` function, but will randomize to an integer value if both start/end are
|
||||
integers. Without argument, will return a float between 0 and 1.
|
||||
- `$randint([start, [end]])` ([code](api:evennia.utils.funcparser#evennia.utils.funcparser.funcparser_callable_randint)) -
|
||||
works like the `randint()` python function and always returns an integer.
|
||||
- `$choice(list)` ([code](api:evennia.utils.funcparser#evennia.utils.funcparser.funcparser_callable_choice)) -
|
||||
the input will automatically be parsed the same way as `$eval` and is expected to be an iterable. A random
|
||||
element of this list will be returned.
|
||||
- `$pad(text[, width, align, fillchar])` ([code](api:evennia.utils.funcparser#evennia.utils.funcparser.funcparser_callable_pad)) -
|
||||
this will pad content. `$pad("Hello", 30, c, -)` will lead to a text centered in a 30-wide block surrounded by `-`
|
||||
characters.
|
||||
- `$crop(text, width=78, suffix='[...]')` ([code](api:evennia.utils.funcparser#evennia.utils.funcparser.funcparser_callable_crop)) -
|
||||
this will crop a text longer than the width, by default ending it with a `[...]`-suffix that also fits within
|
||||
the width. If no width is given, the client width or `settings.DEFAULT_CLIENT_WIDTH` will be used.
|
||||
- `$space(num)` ([code](api:evennia.utils.funcparser#evennia.utils.funcparser.funcparser_callable_space)) -
|
||||
this will insert `num` spaces.
|
||||
- `$just(string, width=40, align=c, indent=2)` ([code](api:evennia.utils.funcparser#evennia.utils.funcparser.funcparser_callable_justify)) -
|
||||
justifies the text to a given width, aligning it left/right/center or 'f' for full (spread text across width).
|
||||
- `$ljust` - shortcut to justify-left. Takes all other kwarg of `$just`.
|
||||
- `$rjust` - shortcut to right justify.
|
||||
- `$cjust` - shortcut to center justify.
|
||||
- `$clr(startcolor, text[, endcolor])` ([code](api:evennia.utils.funcparser#evennia.utils.funcparser.funcparser_callable_clr)) -
|
||||
color text. The color is given with one or two characters without the preceeding `|`. If no endcolor is
|
||||
given, the string will go back to neutral, so `$clr(r, Hello)` is equivalent to `|rHello|n`.
|
||||
|
||||
### `evennia.utils.funcparser.SEARCHING_CALLABLES`
|
||||
|
||||
These are callables that requires access-checks in order to search for objects. So they require some
|
||||
extra reserved kwargs to be passed when running the parser:
|
||||
|
||||
```python
|
||||
parser.parse_to_any(string, caller=<object or account>, access="control", ...)`
|
||||
|
||||
```
|
||||
The `caller` is required, it's the the object to do the access-check for. The `access` kwarg is the
|
||||
[lock type](./Locks) to check, default being `"control"`.
|
||||
|
||||
- `$search(query,type=account|script,return_list=False)` ([code](api:evennia.utils.funcparser#evennia.utils.funcparser.funcparser_callable_search)) -
|
||||
this will look up and try to match an object by key or alias. Use the `type` kwarg to
|
||||
search for `account` or `script` instead. By default this will return nothing if there are more than one
|
||||
match; if `return_list` is `True` a list of 0, 1 or more matches will be returned instead.
|
||||
- `$obj(query)`, `$dbref(query)` - legacy aliases for `$search`.
|
||||
- `$objlist(query)` - legacy alias for `$search`, always returning a list.
|
||||
|
||||
|
||||
### `evennia.utils.funcparser.ACTOR_STANCE_CALLABLES`
|
||||
|
||||
These are used to implement actor-stance emoting. They are used by the
|
||||
[DefaultObject.msg_contents](api:evennia.objects.objects#evennia.objects.objects.DefaultObject.msg_contents) method
|
||||
by default.
|
||||
|
||||
These all require extra kwargs be passed into the parser:
|
||||
|
||||
```python
|
||||
parser.parse(string, caller=<obj>, receiver=<obj>, mapping={'key': <obj>, ...})
|
||||
```
|
||||
|
||||
Here the `caller` is the one sending the message and `receiver` the one to see it. The `mapping` contains
|
||||
references to other objects accessible via these callables.
|
||||
|
||||
- `$you([key])` ([code](api:evennia.utils.funcparser#evennia.utils.funcparser.funcparser_callable_you)) -
|
||||
if no `key` is given, this represents the `caller`, otherwise an object from `mapping`
|
||||
will be used. As this message is sent to different recipients, the `receiver` will change and this will
|
||||
be replaced either with the string `you` (if you and the receiver is the same entity) or with the
|
||||
result of `you_obj.get_display_name(looker=receiver)`. This allows for a single string to echo differently
|
||||
depending on who sees it, and also to reference other people in the same way.
|
||||
- `$You([key])` - same as `$you` but always capitalized.
|
||||
- `$conj(verb)` ([code](api:evennia.utils.funcparser#evennia.utils.funcparser.funcparser_callable_conjugate)) -- conjugates a verb between 4nd person presens to 3rd person presence depending on who
|
||||
sees the string. For example `"$You() $conj(smiles)".` will show as "You smile." and "Tom smiles." depending
|
||||
on who sees it. This makes use of the tools in [evennia.utils.verb_conjugation](api:evennia.utils.verb_conjugation)
|
||||
to do this, and only works for English verbs.
|
||||
|
||||
### Example
|
||||
|
||||
Here's an example of including the default callables together with two custom ones.
|
||||
|
||||
```python
|
||||
from evennia.utils import funcparser
|
||||
from evennia.utils import gametime
|
||||
|
||||
def _dashline(*args, **kwargs):
|
||||
if args:
|
||||
return f"\n-------- {args[0]} --------"
|
||||
return ''
|
||||
|
||||
def _uptime(*args, **kwargs):
|
||||
return gametime.uptime()
|
||||
|
||||
callables = {
|
||||
"dashline": _dashline,
|
||||
"uptime": _uptime,
|
||||
**funcparser.FUNCPARSER_CALLABLES,
|
||||
**funcparser.ACTOR_STANCE_CALLABLES,
|
||||
**funcparser.SEARCHING_CALLABLES
|
||||
}
|
||||
|
||||
parser = funcparser.FuncParser(callables)
|
||||
|
||||
string = "This is the current uptime:$dashline($toint($uptime()) seconds)"
|
||||
result = parser.parse(string)
|
||||
|
||||
```
|
||||
|
||||
Above we define two callables `_dashline` and `_uptime` and map them to names `"dashline"` and `"uptime"`,
|
||||
which is what we then can call as `$header` and `$uptime` in the string. We also have access to
|
||||
all the defaults (like `$toint()`).
|
||||
|
||||
The parsed result of the above would be something like this:
|
||||
|
||||
This is the current uptime:
|
||||
------- 343 seconds -------
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
Whether due to abuse, blatant breaking of your rules, or some other reason, you will eventually find
|
||||
no other recourse but to kick out a particularly troublesome player. The default command set has
|
||||
admin tools to handle this, primarily `@ban`, `@unban`, and `@boot`.
|
||||
admin tools to handle this, primarily `ban`, `unban`, and `boot`.
|
||||
|
||||
## Creating a ban
|
||||
|
||||
|
|
@ -16,7 +16,7 @@ have tried to be nice. Now you just want this troll gone.
|
|||
|
||||
The easiest recourse is to block the account YouSuck from ever connecting again.
|
||||
|
||||
@ban YouSuck
|
||||
ban YouSuck
|
||||
|
||||
This will lock the name YouSuck (as well as 'yousuck' and any other capitalization combination), and
|
||||
next time they try to log in with this name the server will not let them!
|
||||
|
|
@ -24,12 +24,12 @@ next time they try to log in with this name the server will not let them!
|
|||
You can also give a reason so you remember later why this was a good thing (the banned account will
|
||||
never see this)
|
||||
|
||||
@ban YouSuck:This is just a troll.
|
||||
ban YouSuck:This is just a troll.
|
||||
|
||||
If you are sure this is just a spam account, you might even consider deleting the player account
|
||||
outright:
|
||||
|
||||
@delaccount YouSuck
|
||||
accounts/delete YouSuck
|
||||
|
||||
Generally, banning the name is the easier and safer way to stop the use of an account -- if you
|
||||
change your mind you can always remove the block later whereas a deletion is permanent.
|
||||
|
|
@ -49,7 +49,7 @@ the `who` command, which will show you something like this:
|
|||
The "Host" bit is the IP address from which the account is connecting. Use this to define the ban
|
||||
instead of the name:
|
||||
|
||||
@ban 237.333.0.223
|
||||
ban 237.333.0.223
|
||||
|
||||
This will stop YouSuckMore connecting from their computer. Note however that IP address might change
|
||||
easily - either due to how the player's Internet Service Provider operates or by the user simply
|
||||
|
|
@ -58,7 +58,7 @@ groups of three digits in the address. So if you figure out that !YouSuckMore ma
|
|||
237.333.0.223, 237.333.0.225, and 237.333.0.256 (only changes in their subnet), it might be an idea
|
||||
to put down a ban like this to include any number in that subnet:
|
||||
|
||||
@ban 237.333.0.*
|
||||
ban 237.333.0.*
|
||||
|
||||
You should combine the IP ban with a name-ban too of course, so the account YouSuckMore is truly
|
||||
locked regardless of where they connect from.
|
||||
|
|
@ -71,16 +71,16 @@ blocking out innocent players who just happen to connect from the same subnet as
|
|||
YouSuck is not really noticing all this banning yet though - and won't until having logged out and
|
||||
trying to log back in again. Let's help the troll along.
|
||||
|
||||
@boot YouSuck
|
||||
boot YouSuck
|
||||
|
||||
Good riddance. You can give a reason for booting too (to be echoed to the player before getting
|
||||
kicked out).
|
||||
|
||||
@boot YouSuck:Go troll somewhere else.
|
||||
boot YouSuck:Go troll somewhere else.
|
||||
|
||||
### Lifting a ban
|
||||
|
||||
Use the `@unban` (or `@ban`) command without any arguments and you will see a list of all currently
|
||||
Use the `unban` (or `ban`) command without any arguments and you will see a list of all currently
|
||||
active bans:
|
||||
|
||||
Active bans
|
||||
|
|
@ -90,7 +90,7 @@ active bans:
|
|||
|
||||
Use the `id` from this list to find out which ban to lift.
|
||||
|
||||
@unban 2
|
||||
unban 2
|
||||
|
||||
Cleared ban 2: 237.333.0.*
|
||||
|
||||
|
|
@ -132,7 +132,7 @@ case) the lock to fail.
|
|||
- **type thomas = FlowerPot** -- Turn an annoying player into a flower pot (assuming you have a
|
||||
`FlowerPot` typeclass ready)
|
||||
- **userpassword thomas = fooBarFoo** -- Change a user's password
|
||||
- **delaccount thomas** -- Delete a player account (not recommended, use **ban** instead)
|
||||
- **accounts/delete thomas** -- Delete a player account (not recommended, use **ban** instead)
|
||||
|
||||
- **server** -- Show server statistics, such as CPU load, memory usage, and how many objects are
|
||||
cached
|
||||
|
|
@ -141,4 +141,4 @@ cached
|
|||
- **reset** -- Restarts the server, kicking all connections
|
||||
- **shutdown** -- Stops the server cold without it auto-starting again
|
||||
- **py** -- Executes raw Python code, allows for direct inspection of the database and account
|
||||
objects on the fly. For advanced users.
|
||||
objects on the fly. For advanced users.
|
||||
|
|
|
|||
21
docs/source/Concepts/Clickable-Links.md
Normal file
21
docs/source/Concepts/Clickable-Links.md
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
## Clickable links
|
||||
|
||||
Evennia supports clickable links for clients that supports it. This marks certain text so it can be
|
||||
clicked by a mouse and trigger a given Evennia command. To support clickable links, Evennia requires
|
||||
the webclient or an third-party telnet client with [MXP](http://www.zuggsoft.com/zmud/mxp.htm)
|
||||
support (*Note: Evennia only supports clickable links, no other MXP features*).
|
||||
|
||||
- `|lc` to start the link, by defining the command to execute.
|
||||
- `|lt` to continue with the text to show to the user (the link text).
|
||||
- `|le` to end the link text and the link definition.
|
||||
|
||||
All elements must appear in exactly this order to make a valid link. For example,
|
||||
|
||||
```
|
||||
"If you go |lcnorth|ltto the north|le you will find a cottage."
|
||||
```
|
||||
|
||||
This will display as "If you go __to the north__ you will find a cottage." where clicking the link
|
||||
will execute the command `north`. If the client does not support clickable links, only the link text
|
||||
will be shown.
|
||||
|
||||
183
docs/source/Concepts/Colors.md
Normal file
183
docs/source/Concepts/Colors.md
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
# Colors
|
||||
|
||||
*Note that the Documentation does not display colour the way it would look on the screen.*
|
||||
|
||||
Color can be a very useful tool for your game. It can be used to increase readability and make your
|
||||
game more appealing visually.
|
||||
|
||||
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](../Howto/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).
|
||||
|
||||
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.
|
||||
|
||||
Here is an example of the tags in action:
|
||||
|
||||
|rThis text is bright red.|n This is normal text.
|
||||
|RThis is a dark red text.|n This is normal text.
|
||||
|[rThis text has red background.|n This is normal text.
|
||||
|b|[yThis is bright blue text on yellow background.|n This is normal text.
|
||||
|
||||
- `|n` - this tag will turn off all color formatting, including background colors.
|
||||
- `|#`- markup marks the start of foreground color. The case defines if the text is "bright" or
|
||||
"normal". So `|g` is a bright green and `|G` is "normal" (darker) green.
|
||||
- `|[#` is used to add a background colour to the text. The case again specifies if it is "bright"
|
||||
or "normal", so `|[c` starts a bright cyan background and `|[C` a darker cyan background.
|
||||
- `|!#` is used to add foreground color without any enforced brightness/normal information.
|
||||
These are normal-intensity and are thus always given as uppercase, such as
|
||||
`|!R` for red. The difference between e.g. `|!R` and `|R` is that
|
||||
`|!R` will "inherit" the brightness setting from previously set color tags, whereas `|R` will
|
||||
always reset to the normal-intensity red. The `|#` format contains an implicit `|h`/`|H` tag in it:
|
||||
disabling highlighting when switching to a normal color, and enabling it for bright ones. So `|btest
|
||||
|!Rtest2` will result in a bright red `test2` since the brightness setting from `|b` "bleeds over".
|
||||
You could use this to for example quickly switch the intensity of a multitude of color tags. There
|
||||
is no background-color equivalent to `|!` style tags.
|
||||
- `|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.
|
||||
|
||||
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 `|`:
|
||||
|
||||
```
|
||||
say The ||r ANSI marker changes text color to bright red.
|
||||
```
|
||||
|
||||
This will output the raw `|r` without any color change. This can also be necessary if you are doing
|
||||
ansi art that uses `|` with a letter directly following it.
|
||||
|
||||
Use the command
|
||||
|
||||
@color ansi
|
||||
|
||||
to get a list of all supported ANSI colours and the tags used to produce them.
|
||||
|
||||
A few additional ANSI codes are supported:
|
||||
|
||||
- `|/` A line break. You cannot put the normal Python `\n` line breaks in text entered inside the
|
||||
game (Evennia will filter this for security reasons). This is what you use instead: use the `|/`
|
||||
marker to format text with line breaks from the game command line.
|
||||
- `` This will translate into a `TAB` character. This will not always show (or show differently) to
|
||||
the client since it depends on their local settings. It's often better to use multiple spaces.
|
||||
- `|_` This is a space. You can usually use the normal space character, but if the space is *at the
|
||||
end of the line*, Evennia will likely crop it. This tag will not be cropped but always result in a
|
||||
space.
|
||||
- `|*` This will invert the current text/background colours. Can be useful to mark things (but see
|
||||
below).
|
||||
|
||||
##### Caveats of `|*`
|
||||
|
||||
The `|*` tag (inverse video) is an old ANSI standard and should usually not be used for more than to
|
||||
mark short snippets of text. If combined with other tags it comes with a series of potentially
|
||||
confusing behaviors:
|
||||
|
||||
* The `|*` tag will only work once in a row:, ie: after using it once it won't have an effect again
|
||||
until you declare another tag. This is an example:
|
||||
|
||||
```
|
||||
Normal text, |*reversed text|*, still reversed text.
|
||||
```
|
||||
|
||||
that is, it will not reverse to normal at the second `|*`. You need to reset it manually:
|
||||
|
||||
```
|
||||
Normal text, |*reversed text|n, normal again.
|
||||
```
|
||||
|
||||
* The `|*` tag does not take "bright" colors into account:
|
||||
|
||||
```
|
||||
|RNormal red, |hnow brightened. |*BG is normal red.
|
||||
```
|
||||
|
||||
So `|*` only considers the 'true' foreground color, ignoring any highlighting. Think of the bright
|
||||
state (`|h`) as something like like `<strong>` in HTML: it modifies the _appearance_ of a normal
|
||||
foreground color to match its bright counterpart, without changing its normal color.
|
||||
* Finally, after a `|*`, if the previous background was set to a dark color (via `|[`), `|!#`) will
|
||||
actually change the background color instead of the foreground:
|
||||
|
||||
```
|
||||
|*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.
|
||||
|
||||
### Xterm256 Colours
|
||||
|
||||
The _Xterm256_ standard is a colour scheme that supports 256 colours for text and/or background.
|
||||
While this offers many more possibilities than traditional ANSI colours, be wary that too many text
|
||||
colors will be confusing to the eye. Also, not all clients support Xterm256 - these will instead see
|
||||
the closest equivalent ANSI color. You can mix Xterm256 tags with ANSI tags as you please.
|
||||
|
||||
|555 This is pure white text.|n This is normal text.
|
||||
|230 This is olive green text.
|
||||
|[300 This text has a dark red background.
|
||||
|005|[054 This is dark blue text on a bright cyan background.
|
||||
|=a This is a greyscale value, equal to black.
|
||||
|=m This is a greyscale value, midway between white and black.
|
||||
|=z This is a greyscale value, equal to white.
|
||||
|[=m This is a background greyscale value.
|
||||
|
||||
- `|###` - markup consists of three digits, each an integer from 0 to 5. The three digits describe
|
||||
the amount of **r**ed, **g**reen and **b**lue (RGB) components used in the colour. So `|500` means
|
||||
maximum red and none of the other colours - the result is a bright red. `|520` is red with a touch
|
||||
of green - the result is orange. As opposed to ANSI colors, Xterm256 syntax does not worry about
|
||||
bright/normal intensity, a brighter (lighter) color is just achieved by upping all RGB values with
|
||||
the same amount.
|
||||
- `|[###` - this works the same way but produces a coloured background.
|
||||
- `|=#` - markup produces the xterm256 gray scale tones, where `#` is a letter from `a` (black) to
|
||||
`z` (white). This offers many more nuances of gray than the normal `|###` markup (which only has
|
||||
four gray tones between solid black and white (`|000`, `|111`, `|222`, `|333` and `|444`)).
|
||||
- `|[=#` - this works in the same way but produces background gray scale tones.
|
||||
|
||||
If you have a client that supports Xterm256, you can use
|
||||
|
||||
@color xterm256
|
||||
|
||||
to get a table of all the 256 colours and the codes that produce them. If the table looks broken up
|
||||
into a few blocks of colors, it means Xterm256 is not supported and ANSI are used as a replacement.
|
||||
You can use the `@options` command to see if xterm256 is active for you. This depends on if your
|
||||
client told Evennia what it supports - if not, and you know what your client supports, you may have
|
||||
to activate some features manually.
|
||||
|
||||
## More reading
|
||||
|
||||
There is an [Understanding Color Tags](../Howto/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.
|
||||
|
||||
|
|
@ -1,340 +1,19 @@
|
|||
# TextTags
|
||||
|
||||
|
||||
This documentation details the various text tags supported by Evennia, namely *colours*, *command
|
||||
links* and *inline functions*.
|
||||
|
||||
There is also an [Understanding Color Tags](../Howto/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
|
||||
|
||||
*Note that the Documentation does not display colour the way it would look on the screen.*
|
||||
|
||||
Color can be a very useful tool for your game. It can be used to increase readability and make your
|
||||
game more appealing visually.
|
||||
|
||||
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](../Howto/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).
|
||||
|
||||
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.
|
||||
|
||||
Here is an example of the tags in action:
|
||||
|
||||
|rThis text is bright red.|n This is normal text.
|
||||
|RThis is a dark red text.|n This is normal text.
|
||||
|[rThis text has red background.|n This is normal text.
|
||||
|b|[yThis is bright blue text on yellow background.|n This is normal text.
|
||||
|
||||
- `|n` - this tag will turn off all color formatting, including background colors.
|
||||
- `|#`- markup marks the start of foreground color. The case defines if the text is "bright" or
|
||||
"normal". So `|g` is a bright green and `|G` is "normal" (darker) green.
|
||||
- `|[#` is used to add a background colour to the text. The case again specifies if it is "bright"
|
||||
or "normal", so `|[c` starts a bright cyan background and `|[C` a darker cyan background.
|
||||
- `|!#` is used to add foreground color without any enforced brightness/normal information.
|
||||
These are normal-intensity and are thus always given as uppercase, such as
|
||||
`|!R` for red. The difference between e.g. `|!R` and `|R` is that
|
||||
`|!R` will "inherit" the brightness setting from previously set color tags, whereas `|R` will
|
||||
always reset to the normal-intensity red. The `|#` format contains an implicit `|h`/`|H` tag in it:
|
||||
disabling highlighting when switching to a normal color, and enabling it for bright ones. So `|btest
|
||||
|!Rtest2` will result in a bright red `test2` since the brightness setting from `|b` "bleeds over".
|
||||
You could use this to for example quickly switch the intensity of a multitude of color tags. There
|
||||
is no background-color equivalent to `|!` style tags.
|
||||
- `|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.
|
||||
|
||||
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 `|`:
|
||||
|
||||
```
|
||||
say The ||r ANSI marker changes text color to bright red.
|
||||
```
|
||||
|
||||
This will output the raw `|r` without any color change. This can also be necessary if you are doing
|
||||
ansi art that uses `|` with a letter directly following it.
|
||||
|
||||
Use the command
|
||||
|
||||
@color ansi
|
||||
|
||||
to get a list of all supported ANSI colours and the tags used to produce them.
|
||||
|
||||
A few additional ANSI codes are supported:
|
||||
|
||||
- `|/` A line break. You cannot put the normal Python `\n` line breaks in text entered inside the
|
||||
game (Evennia will filter this for security reasons). This is what you use instead: use the `|/`
|
||||
marker to format text with line breaks from the game command line.
|
||||
- `` This will translate into a `TAB` character. This will not always show (or show differently) to
|
||||
the client since it depends on their local settings. It's often better to use multiple spaces.
|
||||
- `|_` This is a space. You can usually use the normal space character, but if the space is *at the
|
||||
end of the line*, Evennia will likely crop it. This tag will not be cropped but always result in a
|
||||
space.
|
||||
- `|*` This will invert the current text/background colours. Can be useful to mark things (but see
|
||||
below).
|
||||
|
||||
##### Caveats of `|*`
|
||||
|
||||
The `|*` tag (inverse video) is an old ANSI standard and should usually not be used for more than to
|
||||
mark short snippets of text. If combined with other tags it comes with a series of potentially
|
||||
confusing behaviors:
|
||||
|
||||
* The `|*` tag will only work once in a row:, ie: after using it once it won't have an effect again
|
||||
until you declare another tag. This is an example:
|
||||
|
||||
```
|
||||
Normal text, |*reversed text|*, still reversed text.
|
||||
```
|
||||
|
||||
that is, it will not reverse to normal at the second `|*`. You need to reset it manually:
|
||||
|
||||
```
|
||||
Normal text, |*reversed text|n, normal again.
|
||||
```
|
||||
|
||||
* The `|*` tag does not take "bright" colors into account:
|
||||
|
||||
```
|
||||
|RNormal red, |hnow brightened. |*BG is normal red.
|
||||
```
|
||||
|
||||
So `|*` only considers the 'true' foreground color, ignoring any highlighting. Think of the bright
|
||||
state (`|h`) as something like like `<strong>` in HTML: it modifies the _appearance_ of a normal
|
||||
foreground color to match its bright counterpart, without changing its normal color.
|
||||
* Finally, after a `|*`, if the previous background was set to a dark color (via `|[`), `|!#`) will
|
||||
actually change the background color instead of the foreground:
|
||||
|
||||
```
|
||||
|*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.
|
||||
|
||||
### Xterm256 Colours
|
||||
|
||||
The _Xterm256_ standard is a colour scheme that supports 256 colours for text and/or background.
|
||||
While this offers many more possibilities than traditional ANSI colours, be wary that too many text
|
||||
colors will be confusing to the eye. Also, not all clients support Xterm256 - these will instead see
|
||||
the closest equivalent ANSI color. You can mix Xterm256 tags with ANSI tags as you please.
|
||||
|
||||
|555 This is pure white text.|n This is normal text.
|
||||
|230 This is olive green text.
|
||||
|[300 This text has a dark red background.
|
||||
|005|[054 This is dark blue text on a bright cyan background.
|
||||
|=a This is a greyscale value, equal to black.
|
||||
|=m This is a greyscale value, midway between white and black.
|
||||
|=z This is a greyscale value, equal to white.
|
||||
|[=m This is a background greyscale value.
|
||||
|
||||
- `|###` - markup consists of three digits, each an integer from 0 to 5. The three digits describe
|
||||
the amount of **r**ed, **g**reen and **b**lue (RGB) components used in the colour. So `|500` means
|
||||
maximum red and none of the other colours - the result is a bright red. `|520` is red with a touch
|
||||
of green - the result is orange. As opposed to ANSI colors, Xterm256 syntax does not worry about
|
||||
bright/normal intensity, a brighter (lighter) color is just achieved by upping all RGB values with
|
||||
the same amount.
|
||||
- `|[###` - this works the same way but produces a coloured background.
|
||||
- `|=#` - markup produces the xterm256 gray scale tones, where `#` is a letter from `a` (black) to
|
||||
`z` (white). This offers many more nuances of gray than the normal `|###` markup (which only has
|
||||
four gray tones between solid black and white (`|000`, `|111`, `|222`, `|333` and `|444`)).
|
||||
- `|[=#` - this works in the same way but produces background gray scale tones.
|
||||
|
||||
If you have a client that supports Xterm256, you can use
|
||||
|
||||
@color xterm256
|
||||
|
||||
to get a table of all the 256 colours and the codes that produce them. If the table looks broken up
|
||||
into a few blocks of colors, it means Xterm256 is not supported and ANSI are used as a replacement.
|
||||
You can use the `@options` command to see if xterm256 is active for you. This depends on if your
|
||||
client told Evennia what it supports - if not, and you know what your client supports, you may have
|
||||
to activate some features manually.
|
||||
|
||||
## Clickable links
|
||||
|
||||
Evennia supports clickable links for clients that supports it. This marks certain text so it can be
|
||||
clicked by a mouse and trigger a given Evennia command. To support clickable links, Evennia requires
|
||||
the webclient or an third-party telnet client with [MXP](http://www.zuggsoft.com/zmud/mxp.htm)
|
||||
support (*Note: Evennia only supports clickable links, no other MXP features*).
|
||||
|
||||
- `|lc` to start the link, by defining the command to execute.
|
||||
- `|lt` to continue with the text to show to the user (the link text).
|
||||
- `|le` to end the link text and the link definition.
|
||||
|
||||
All elements must appear in exactly this order to make a valid link. For example,
|
||||
|
||||
```
|
||||
"If you go |lcnorth|ltto the north|le you will find a cottage."
|
||||
```
|
||||
|
||||
This will display as "If you go __to the north__ you will find a cottage." where clicking the link
|
||||
will execute the command `north`. If the client does not support clickable links, only the link text
|
||||
will be shown.
|
||||
|
||||
## Inline functions
|
||||
|
||||
> Note: Inlinefuncs are **not** activated by default. To use them you need to add
|
||||
`INLINEFUNC_ENABLED=True` to your settings file.
|
||||
|
||||
Evennia has its own inline text formatting language, known as *inlinefuncs*. It allows the builder
|
||||
to include special function calls in code. They are executed dynamically by each session that
|
||||
receives them.
|
||||
|
||||
To add an inlinefunc, you embed it in a text string like this:
|
||||
|
||||
```
|
||||
"A normal string with $funcname(arg, arg, ...) embedded inside it."
|
||||
```
|
||||
|
||||
When this string is sent to a session (with the `msg()` method), these embedded inlinefuncs will be
|
||||
parsed. Their return value (which always is a string) replace their call location in the finalized
|
||||
string. The interesting thing with this is that the function called will have access to which
|
||||
session is seeing the string, meaning the string can end up looking different depending on who is
|
||||
looking. It could of course also vary depending on other factors like game time.
|
||||
|
||||
Any number of comma-separated arguments can be given (or none). No keywords are supported. You can
|
||||
also nest inlinefuncs by letting an argument itself also be another `$funcname(arg, arg, ...)` call
|
||||
(down to any depth of nesting). Function call resolution happens as in all programming languages
|
||||
inside-out, with the nested calls replacing the argument with their return strings before calling he
|
||||
parent.
|
||||
|
||||
```
|
||||
> say "This is $pad(a center-padded text, 30,c,-) of width 30."
|
||||
You say, "This is ---- a center-padded text----- of width 30."
|
||||
```
|
||||
|
||||
A special case happens if wanting to use an inlinefunc argument that itself includes a comma - this
|
||||
would be parsed as an argument separator. To escape commas you can either escape each comma manually
|
||||
with a backslash `\,`, or you can embed the entire string in python triple-quotes `"""` or `'''` -
|
||||
this will escape the entire argument, including commas and any nested inlinefunc calls within.
|
||||
|
||||
Only certain functions are available to use as inlinefuncs and the game developer may add their own
|
||||
functions as needed.
|
||||
|
||||
### New inlinefuncs
|
||||
|
||||
To add new inlinefuncs, edit the file `mygame/server/conf/inlinefuncs.py`.
|
||||
|
||||
*All globally defined functions in this module* are considered inline functions by the system. The
|
||||
only exception is functions whose name starts with an underscore `_`. An inlinefunc must be of the
|
||||
following form:
|
||||
|
||||
```python
|
||||
def funcname(*args, **kwargs):
|
||||
# ...
|
||||
return modified_text
|
||||
```
|
||||
|
||||
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](../Components/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.
|
||||
|
||||
Here is an example, the `crop` default inlinefunction:
|
||||
|
||||
```python
|
||||
from evennia.utils import utils
|
||||
|
||||
def crop(*args, **kwargs):
|
||||
"""
|
||||
Inlinefunc. Crops ingoing text to given widths.
|
||||
Args:
|
||||
text (str, optional): Text to crop.
|
||||
width (str, optional): Will be converted to an integer. Width of
|
||||
crop in characters.
|
||||
suffix (str, optional): End string to mark the fact that a part
|
||||
of the string was cropped. Defaults to `[...]`.
|
||||
Kwargs:
|
||||
session (Session): Session performing the crop.
|
||||
Example:
|
||||
`$crop(text, 50, [...])`
|
||||
|
||||
"""
|
||||
text, width, suffix = "", 78, "[...]"
|
||||
nargs = len(args)
|
||||
if nargs > 0:
|
||||
text = args[0]
|
||||
if nargs > 1:
|
||||
width = int(args[1]) if args[1].strip().isdigit() else 78
|
||||
if nargs > 2:
|
||||
suffix = args[2]
|
||||
return utils.crop(text, width=width, suffix=suffix)
|
||||
```
|
||||
Another example, making use of the Session:
|
||||
|
||||
```python
|
||||
def charactername(*args, **kwargs):
|
||||
"""
|
||||
Inserts the character name of whomever sees the string
|
||||
(so everyone will see their own name). Uses the account
|
||||
name for OOC communications.
|
||||
|
||||
Example:
|
||||
say "This means YOU, $charactername()!"
|
||||
|
||||
"""
|
||||
session = kwargs["session"]
|
||||
if session.puppet:
|
||||
return kwargs["session"].puppet.key
|
||||
else:
|
||||
return session.account.key
|
||||
```
|
||||
|
||||
Evennia itself offers the following default inline functions (mostly as examples):
|
||||
|
||||
* `crop(text, width, suffix)` - See above.
|
||||
* `pad(text, width, align, fillchar)` - this pads the text to `width` (default 78), alignment ("c",
|
||||
"l" or "r", defaulting to "c") and fill-in character (defaults to space). Example: `$pad(40,l,-)`
|
||||
* `clr(startclr, text, endclr)` - A programmatic way to enter colored text for those who don't want
|
||||
to use the normal `|c` type color markers for some reason. The `color` argument is the same as the
|
||||
color markers except without the actual pre-marker, so `|r` would be just `r`. If `endclr` is not
|
||||
given, it defaults to resetting the color (`n`). Example: `$clr(b, A blue text)`
|
||||
* `space(number)` - Inserts the given number of spaces. If no argument is given, use 4 spaces.
|
||||
# In-text tags parsed by Evennia
|
||||
|
||||
Evennia understands various extra information embedded in text:
|
||||
|
||||
- [Colors](./Colors) - Using `|r`, `|n` etc can be used to mark parts of text with a color. The color will
|
||||
become ANSI/XTerm256 color tags for Telnet connections and CSS information for the webclient.
|
||||
- [Clickable links](./Clickable-Links) - This allows you to provide a text the user can click to execute an
|
||||
in-game command. This is on the form `|lc command |lt text |le`.
|
||||
- [FuncParser callables](../Components/FuncParser) - These are full-fledged function calls on the form `$funcname(args, kwargs)`
|
||||
that lead to calls to Python functions. The parser can be run with different available callables in different
|
||||
circumstances. The parser is run on all outgoing messages if `settings.FUNCPARSER_PARSE_OUTGOING_MESSAGES_ENABLED=True`
|
||||
(disabled by default).
|
||||
|
||||
```toctree::
|
||||
|
||||
Colors.md
|
||||
Clickable-Links.md
|
||||
../Components/FuncParser.md
|
||||
```
|
||||
|
|
@ -77,6 +77,7 @@ The flat API is defined in `__init__.py` [viewable here](github:evennia/__init__
|
|||
- [evennia.EvForm](api:evennia.utils.evform#evennia.utils.evform.EvForm) - text form creator
|
||||
- Evennia.EvMore - text paginator
|
||||
- [evennia.EvEditor](api:evennia.utils.eveditor#evennia.utils.eveditor.EvEditor) - in game text line editor ([docs](Components/EvEditor))
|
||||
- [evennia.utils.funcparser.Funcparser](api:evennia.utils.funcparser) - inline parsing of functions ([docs](Components/FuncParser))
|
||||
|
||||
### Global singleton handlers
|
||||
|
||||
|
|
|
|||
7
docs/source/api/evennia.utils.funcparser.rst
Normal file
7
docs/source/api/evennia.utils.funcparser.rst
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
evennia.utils.funcparser
|
||||
===============================
|
||||
|
||||
.. automodule:: evennia.utils.funcparser
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
evennia.utils.inlinefuncs
|
||||
================================
|
||||
|
||||
.. automodule:: evennia.utils.inlinefuncs
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
|
@ -21,8 +21,8 @@ evennia.utils
|
|||
evennia.utils.evmenu
|
||||
evennia.utils.evmore
|
||||
evennia.utils.evtable
|
||||
evennia.utils.funcparser
|
||||
evennia.utils.gametime
|
||||
evennia.utils.inlinefuncs
|
||||
evennia.utils.logger
|
||||
evennia.utils.optionclasses
|
||||
evennia.utils.optionhandler
|
||||
|
|
@ -38,3 +38,4 @@ evennia.utils
|
|||
:maxdepth: 6
|
||||
|
||||
evennia.utils.idmapper
|
||||
evennia.utils.verb_conjugation
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
evennia.utils.verb\_conjugation.conjugate
|
||||
================================================
|
||||
|
||||
.. automodule:: evennia.utils.verb_conjugation.conjugate
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
15
docs/source/api/evennia.utils.verb_conjugation.rst
Normal file
15
docs/source/api/evennia.utils.verb_conjugation.rst
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
evennia.utils.verb\_conjugation
|
||||
=======================================
|
||||
|
||||
.. automodule:: evennia.utils.verb_conjugation
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 6
|
||||
|
||||
evennia.utils.verb_conjugation.conjugate
|
||||
evennia.utils.verb_conjugation.tests
|
||||
7
docs/source/api/evennia.utils.verb_conjugation.tests.rst
Normal file
7
docs/source/api/evennia.utils.verb_conjugation.tests.rst
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
evennia.utils.verb\_conjugation.tests
|
||||
============================================
|
||||
|
||||
.. automodule:: evennia.utils.verb_conjugation.tests
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
# Toc
|
||||
|
||||
- [API root](api/evennia-api.rst)
|
||||
- [Coding/Coding Introduction](Coding/Coding-Introduction)
|
||||
- [Coding/Coding Overview](Coding/Coding-Overview)
|
||||
- [Coding/Continuous Integration](Coding/Continuous-Integration)
|
||||
|
|
@ -29,6 +29,7 @@
|
|||
- [Components/EvEditor](Components/EvEditor)
|
||||
- [Components/EvMenu](Components/EvMenu)
|
||||
- [Components/EvMore](Components/EvMore)
|
||||
- [Components/FuncParser](Components/FuncParser)
|
||||
- [Components/Help System](Components/Help-System)
|
||||
- [Components/Inputfuncs](Components/Inputfuncs)
|
||||
- [Components/Locks](Components/Locks)
|
||||
|
|
@ -52,6 +53,8 @@
|
|||
- [Concepts/Banning](Concepts/Banning)
|
||||
- [Concepts/Bootstrap & Evennia](Concepts/Bootstrap-&-Evennia)
|
||||
- [Concepts/Building Permissions](Concepts/Building-Permissions)
|
||||
- [Concepts/Clickable Links](Concepts/Clickable-Links)
|
||||
- [Concepts/Colors](Concepts/Colors)
|
||||
- [Concepts/Concepts Overview](Concepts/Concepts-Overview)
|
||||
- [Concepts/Custom Protocols](Concepts/Custom-Protocols)
|
||||
- [Concepts/Guest Logins](Concepts/Guest-Logins)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue