From 70b4caedb68d42255437d2ec2de6741dbaa390ec Mon Sep 17 00:00:00 2001
From: Evennia docbuilder action Here, __unloggedin_look_command [l, look] (cmdset: UnloggedinCmdSet, help-category: General) __unloggedin_look_command [look, l] (cmdset: UnloggedinCmdSet, help-category: General) about [version] (cmdset: CharacterCmdSet, help-category: System) access [hierarchy, groups] (cmdset: CharacterCmdSet, help-category: General) accounts [account, listaccounts] (cmdset: CharacterCmdSet, help-category: System) addcom [aliaschan, chanalias] (cmdset: AccountCmdSet, help-category: Comms) addcom [chanalias, aliaschan] (cmdset: AccountCmdSet, help-category: Comms) alias [setobjalias] (cmdset: CharacterCmdSet, help-category: Building) allcom (cmdset: AccountCmdSet, help-category: Comms) batchcode [batchcodes] (cmdset: CharacterCmdSet, help-category: Building) batchcommands [batchcommand, batchcmd] (cmdset: CharacterCmdSet, help-category: Building) batchcommands [batchcmd, batchcommand] (cmdset: CharacterCmdSet, help-category: Building) cboot (cmdset: AccountCmdSet, help-category: Comms) ccreate [channelcreate] (cmdset: AccountCmdSet, help-category: Comms) cdesc (cmdset: AccountCmdSet, help-category: Comms) cdestroy (cmdset: AccountCmdSet, help-category: Comms) cemit [cmsg] (cmdset: AccountCmdSet, help-category: Comms) channels [channellist, chanlist, all channels, comlist, clist] (cmdset: AccountCmdSet, help-category: Comms) channels [channellist, all channels, clist, comlist, chanlist] (cmdset: AccountCmdSet, help-category: Comms) charcreate (cmdset: AccountCmdSet, help-category: General) chardelete (cmdset: AccountCmdSet, help-category: General) clock (cmdset: AccountCmdSet, help-category: Comms)1
+
1
2
3
4
5
6
7
-8
from evennia import Command
+8from evennia import Command
class CmdEcho(Command):
"""
Usage: echo <arg>
@@ -488,8 +488,8 @@ class CmdEcho(Command):
key = "echo"
def func(self):
self.caller.msg(self.args.strip())
-
:linenos: turns on line-numbers and :emphasize-lines: allows for emphasizing certain lines
in a different color. The :caption: shows an instructive text and :name: is used to reference
diff --git a/docs/0.9.5/Default-Commands.html b/docs/0.9.5/Default-Commands.html
index 058d597f21..d2645821c4 100644
--- a/docs/0.9.5/Default-Commands.html
+++ b/docs/0.9.5/Default-Commands.html
@@ -53,21 +53,21 @@ with Batch-Processor’s interactive mode.
-
create [cre, cr] (cmdset: UnloggedinCmdSet, help-category: General)
cwho (cmdset: AccountCmdSet, help-category: Comms)
delcom [delchanalias, delaliaschan] (cmdset: AccountCmdSet, help-category: Comms)
delcom [delaliaschan, delchanalias] (cmdset: AccountCmdSet, help-category: Comms)
desc [describe] (cmdset: CharacterCmdSet, help-category: Building)
destroy [delete, del] (cmdset: CharacterCmdSet, help-category: Building)
destroy [del, delete] (cmdset: CharacterCmdSet, help-category: Building)
dig (cmdset: CharacterCmdSet, help-category: Building)
drop (cmdset: CharacterCmdSet, help-category: General)
encoding [encode] (cmdset: UnloggedinCmdSet, help-category: General)
mvattr (cmdset: CharacterCmdSet, help-category: Building)
name [rename] (cmdset: CharacterCmdSet, help-category: Building)
nick [nicks, nickname] (cmdset: AccountCmdSet, help-category: General)
objects [listobjs, stats, db, listobjects] (cmdset: CharacterCmdSet, help-category: System)
nick [nickname, nicks] (cmdset: AccountCmdSet, help-category: General)
objects [stats, listobjects, listobjs, db] (cmdset: CharacterCmdSet, help-category: System)
ooc [unpuppet] (cmdset: AccountCmdSet, help-category: General)
open (cmdset: CharacterCmdSet, help-category: Building)
option [options] (cmdset: AccountCmdSet, help-category: General)
quell [unquell] (cmdset: AccountCmdSet, help-category: General)
quit (cmdset: AccountCmdSet, help-category: General)
quit [q, qu] (cmdset: UnloggedinCmdSet, help-category: General)
quit [qu, q] (cmdset: UnloggedinCmdSet, help-category: General)
reload [restart] (cmdset: AccountCmdSet, help-category: System)
reset [reboot] (cmdset: AccountCmdSet, help-category: System)
rss2chan (cmdset: AccountCmdSet, help-category: Comms)
time [uptime] (cmdset: CharacterCmdSet, help-category: System)
tunnel [tun] (cmdset: CharacterCmdSet, help-category: Building)
typeclass [parent, type, swap, update] (cmdset: CharacterCmdSet, help-category: Building)
typeclass [parent, swap, type, update] (cmdset: CharacterCmdSet, help-category: Building)
unlink (cmdset: CharacterCmdSet, help-category: Building)
whisper (cmdset: CharacterCmdSet, help-category: General)
who [doing] (cmdset: AccountCmdSet, help-category: General)
var onCustomFunc = function(args, kwargs) {
- var = args.var
- console.log(var)
- }
+ var onCustomFunc = function(args, kwargs) {
+ var = args.var
+ console.log(var)
+ }
You’ll also need to add the function to what the main plugin function returns:
- return {
- init: init,
- onCustomFunc,
- }
+ return {
+ init: init,
+ onCustomFunc,
+ }
This defines the function and looks for “var” as a variable that is passed to it. Once you have this
in place in your custom plugin, you also need to update the static/webclient/js/webclient_gui.js
file to recognize the new function when it’s called. First you should add a new function inside the
plugin_handler function to recognize the new function:
- var onCustomFunc = function (cmdname, args, kwargs) {
- for( let n=0; n < ordered_plugins.length; n++ ) {
- let plugin = ordered_plugins[n];
- if( 'onCustomFunc' in plugin ) {
- if( plugin.onCustomFunc(args, kwargs) ) {
- // True -- means this plugin claims this command exclusively.
- return;
- }
- }
- }
- }
+ var onCustomFunc = function (cmdname, args, kwargs) {
+ for( let n=0; n < ordered_plugins.length; n++ ) {
+ let plugin = ordered_plugins[n];
+ if( 'onCustomFunc' in plugin ) {
+ if( plugin.onCustomFunc(args, kwargs) ) {
+ // True -- means this plugin claims this command exclusively.
+ return;
+ }
+ }
+ }
+ }
This looks through all the plugins for a function that corresponds to the custom function being
called. Next, add the custom function to the return statement of the plugin handler:
- return {
- add: add,
- onKeydown: onKeydown,
- onBeforeUnload: onBeforeUnload,
- onLoggedIn: onLoggedIn,
- onText: onText,
- onGotOptions: onGotOptions,
- onPrompt: onPrompt,
- onDefault: onDefault,
- onSilence: onSilence,
- onConnectionClose: onConnectionClose,
- onSend: onSend,
- init: init,
- postInit: postInit,
- onCustomFunc: onCustomFunc,
- }
+ return {
+ add: add,
+ onKeydown: onKeydown,
+ onBeforeUnload: onBeforeUnload,
+ onLoggedIn: onLoggedIn,
+ onText: onText,
+ onGotOptions: onGotOptions,
+ onPrompt: onPrompt,
+ onDefault: onDefault,
+ onSilence: onSilence,
+ onConnectionClose: onConnectionClose,
+ onSend: onSend,
+ init: init,
+ postInit: postInit,
+ onCustomFunc: onCustomFunc,
+ }
Lastly, you will also need to need to add an entry to the Evennia emitter to tie the python function
call to this new javascript function (this is in the $(document).ready function):
- Evennia.emitter.on("customFunc", plugin_handler.onCustomFunc);
+ Evennia.emitter.on("customFunc", plugin_handler.onCustomFunc);
Now you can make a call from your python code to the new custom function to pass information from
diff --git a/docs/0.9.5/_sources/Default-Commands.md.txt b/docs/0.9.5/_sources/Default-Commands.md.txt
index 581429c3a3..dfcfd1404a 100644
--- a/docs/0.9.5/_sources/Default-Commands.md.txt
+++ b/docs/0.9.5/_sources/Default-Commands.md.txt
@@ -14,21 +14,21 @@ with [EvEditor](./EvEditor.md), flipping pages in [EvMore](./EvMore.md) or using
[Batch-Processor](./Batch-Processors.md)'s interactive mode.
```
-- [**__unloggedin_look_command** [l, look]](evennia.commands.default.unloggedin.CmdUnconnectedLook) (cmdset: [UnloggedinCmdSet](evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet), help-category: _General_)
+- [**__unloggedin_look_command** [look, l]](evennia.commands.default.unloggedin.CmdUnconnectedLook) (cmdset: [UnloggedinCmdSet](evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet), help-category: _General_)
- [**about** [version]](evennia.commands.default.system.CmdAbout) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_)
- [**access** [hierarchy, groups]](evennia.commands.default.general.CmdAccess) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_)
- [**accounts** [account, listaccounts]](evennia.commands.default.system.CmdAccounts) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_)
-- [**addcom** [aliaschan, chanalias]](evennia.commands.default.comms.CmdAddCom) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_)
+- [**addcom** [chanalias, aliaschan]](evennia.commands.default.comms.CmdAddCom) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_)
- [**alias** [setobjalias]](evennia.commands.default.building.CmdSetObjAlias) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**allcom**](evennia.commands.default.comms.CmdAllCom) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_)
- [**batchcode** [batchcodes]](evennia.commands.default.batchprocess.CmdBatchCode) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
-- [**batchcommands** [batchcommand, batchcmd]](evennia.commands.default.batchprocess.CmdBatchCommands) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
+- [**batchcommands** [batchcmd, batchcommand]](evennia.commands.default.batchprocess.CmdBatchCommands) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**cboot**](evennia.commands.default.comms.CmdCBoot) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_)
- [**ccreate** [channelcreate]](evennia.commands.default.comms.CmdChannelCreate) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_)
- [**cdesc**](evennia.commands.default.comms.CmdCdesc) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_)
- [**cdestroy**](evennia.commands.default.comms.CmdCdestroy) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_)
- [**cemit** [cmsg]](evennia.commands.default.comms.CmdCemit) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_)
-- [**channels** [channellist, chanlist, all channels, comlist, clist]](evennia.commands.default.comms.CmdChannels) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_)
+- [**channels** [channellist, all channels, clist, comlist, chanlist]](evennia.commands.default.comms.CmdChannels) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_)
- [**charcreate**](evennia.commands.default.account.CmdCharCreate) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_)
- [**chardelete**](evennia.commands.default.account.CmdCharDelete) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_)
- [**clock**](evennia.commands.default.comms.CmdClock) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_)
@@ -40,9 +40,9 @@ with [EvEditor](./EvEditor.md), flipping pages in [EvMore](./EvMore.md) or using
- [**create**](evennia.commands.default.building.CmdCreate) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**create** [cre, cr]](evennia.commands.default.unloggedin.CmdUnconnectedCreate) (cmdset: [UnloggedinCmdSet](evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet), help-category: _General_)
- [**cwho**](evennia.commands.default.comms.CmdCWho) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_)
-- [**delcom** [delchanalias, delaliaschan]](evennia.commands.default.comms.CmdDelCom) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_)
+- [**delcom** [delaliaschan, delchanalias]](evennia.commands.default.comms.CmdDelCom) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_)
- [**desc** [describe]](evennia.commands.default.building.CmdDesc) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
-- [**destroy** [delete, del]](evennia.commands.default.building.CmdDestroy) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
+- [**destroy** [del, delete]](evennia.commands.default.building.CmdDestroy) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**dig**](evennia.commands.default.building.CmdDig) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**drop**](evennia.commands.default.general.CmdDrop) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_)
- [**encoding** [encode]](evennia.commands.default.unloggedin.CmdUnconnectedEncoding) (cmdset: [UnloggedinCmdSet](evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet), help-category: _General_)
@@ -65,8 +65,8 @@ with [EvEditor](./EvEditor.md), flipping pages in [EvMore](./EvMore.md) or using
- [**look** [l, ls]](evennia.commands.default.general.CmdLook) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_)
- [**mvattr**](evennia.commands.default.building.CmdMvAttr) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**name** [rename]](evennia.commands.default.building.CmdName) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
-- [**nick** [nicks, nickname]](evennia.commands.default.general.CmdNick) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_)
-- [**objects** [listobjs, stats, db, listobjects]](evennia.commands.default.system.CmdObjects) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_)
+- [**nick** [nickname, nicks]](evennia.commands.default.general.CmdNick) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_)
+- [**objects** [stats, listobjects, listobjs, db]](evennia.commands.default.system.CmdObjects) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_)
- [**ooc** [unpuppet]](evennia.commands.default.account.CmdOOC) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_)
- [**open**](evennia.commands.default.building.CmdOpen) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**option** [options]](evennia.commands.default.account.CmdOption) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_)
@@ -76,7 +76,7 @@ with [EvEditor](./EvEditor.md), flipping pages in [EvMore](./EvMore.md) or using
- [**py** [!]](evennia.commands.default.system.CmdPy) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _System_)
- [**quell** [unquell]](evennia.commands.default.account.CmdQuell) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_)
- [**quit**](evennia.commands.default.account.CmdQuit) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_)
-- [**quit** [q, qu]](evennia.commands.default.unloggedin.CmdUnconnectedQuit) (cmdset: [UnloggedinCmdSet](evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet), help-category: _General_)
+- [**quit** [qu, q]](evennia.commands.default.unloggedin.CmdUnconnectedQuit) (cmdset: [UnloggedinCmdSet](evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet), help-category: _General_)
- [**reload** [restart]](evennia.commands.default.system.CmdReload) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _System_)
- [**reset** [reboot]](evennia.commands.default.system.CmdReset) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _System_)
- [**rss2chan**](evennia.commands.default.comms.CmdRSS2Chan) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_)
@@ -99,7 +99,7 @@ with [EvEditor](./EvEditor.md), flipping pages in [EvMore](./EvMore.md) or using
- [**tickers**](evennia.commands.default.system.CmdTickers) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_)
- [**time** [uptime]](evennia.commands.default.system.CmdTime) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_)
- [**tunnel** [tun]](evennia.commands.default.building.CmdTunnel) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
-- [**typeclass** [parent, type, swap, update]](evennia.commands.default.building.CmdTypeclass) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
+- [**typeclass** [parent, swap, type, update]](evennia.commands.default.building.CmdTypeclass) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**unlink**](evennia.commands.default.building.CmdUnLink) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**whisper**](evennia.commands.default.general.CmdWhisper) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_)
- [**who** [doing]](evennia.commands.default.account.CmdWho) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_)
diff --git a/docs/0.9.5/api/evennia.commands.default.batchprocess.html b/docs/0.9.5/api/evennia.commands.default.batchprocess.html
index eddc3b8e06..161ff09962 100644
--- a/docs/0.9.5/api/evennia.commands.default.batchprocess.html
+++ b/docs/0.9.5/api/evennia.commands.default.batchprocess.html
@@ -77,7 +77,7 @@ skipping, reloading etc.
diff --git a/docs/0.9.5/api/evennia.commands.default.building.html b/docs/0.9.5/api/evennia.commands.default.building.html
index 1da8ba359c..74a5121e44 100644
--- a/docs/0.9.5/api/evennia.commands.default.building.html
+++ b/docs/0.9.5/api/evennia.commands.default.building.html
@@ -496,7 +496,7 @@ You can specify the /force switch to bypass this confirmation.
@@ -1186,7 +1186,7 @@ server settings.
diff --git a/docs/0.9.5/api/evennia.commands.default.comms.html b/docs/0.9.5/api/evennia.commands.default.comms.html
index ed634eeea6..87962fc6fb 100644
--- a/docs/0.9.5/api/evennia.commands.default.comms.html
+++ b/docs/0.9.5/api/evennia.commands.default.comms.html
@@ -66,7 +66,7 @@ aliases to an already joined channel.
@@ -118,7 +118,7 @@ for that channel.
@@ -221,7 +221,7 @@ Use addcom/delcom to join and leave channels
-
-
aliases = ['channellist', 'chanlist', 'all channels', 'comlist', 'clist']¶
+aliases = ['channellist', 'all channels', 'clist', 'comlist', 'chanlist']¶
diff --git a/docs/0.9.5/api/evennia.commands.default.general.html b/docs/0.9.5/api/evennia.commands.default.general.html
index 1a4e67cb25..5bfb6eaca1 100644
--- a/docs/0.9.5/api/evennia.commands.default.general.html
+++ b/docs/0.9.5/api/evennia.commands.default.general.html
@@ -197,7 +197,7 @@ for everyone to use, you need build privileges and the alias command.
diff --git a/docs/0.9.5/api/evennia.commands.default.system.html b/docs/0.9.5/api/evennia.commands.default.system.html
index 83bf5cb8b6..b297acdf90 100644
--- a/docs/0.9.5/api/evennia.commands.default.system.html
+++ b/docs/0.9.5/api/evennia.commands.default.system.html
@@ -351,7 +351,7 @@ given, <nr> defaults to 10.
-
-
aliases = ['listobjs', 'stats', 'db', 'listobjects']¶
+aliases = ['stats', 'listobjects', 'listobjs', 'db']¶
diff --git a/docs/0.9.5/api/evennia.commands.default.unloggedin.html b/docs/0.9.5/api/evennia.commands.default.unloggedin.html
index 73598d6033..0207566631 100644
--- a/docs/0.9.5/api/evennia.commands.default.unloggedin.html
+++ b/docs/0.9.5/api/evennia.commands.default.unloggedin.html
@@ -165,7 +165,7 @@ version is a bit more complicated.
@@ -210,7 +210,7 @@ All it does is display the connect screen.
diff --git a/docs/0.9.5/api/evennia.contrib.barter.html b/docs/0.9.5/api/evennia.contrib.barter.html
index c0def718e9..aaa45d309f 100644
--- a/docs/0.9.5/api/evennia.contrib.barter.html
+++ b/docs/0.9.5/api/evennia.contrib.barter.html
@@ -653,7 +653,7 @@ try to influence the other part in the deal.
diff --git a/docs/0.9.5/api/evennia.contrib.dice.html b/docs/0.9.5/api/evennia.contrib.dice.html
index 6dc941e2e3..31f97ae1cb 100644
--- a/docs/0.9.5/api/evennia.contrib.dice.html
+++ b/docs/0.9.5/api/evennia.contrib.dice.html
@@ -151,7 +151,7 @@ everyone but the person rolling.
diff --git a/docs/0.9.5/api/evennia.contrib.email_login.html b/docs/0.9.5/api/evennia.contrib.email_login.html
index 6f734bd97a..0253eaf64b 100644
--- a/docs/0.9.5/api/evennia.contrib.email_login.html
+++ b/docs/0.9.5/api/evennia.contrib.email_login.html
@@ -173,7 +173,7 @@ version is a bit more complicated.
@@ -213,7 +213,7 @@ All it does is display the connect screen.
diff --git a/docs/0.9.5/api/evennia.contrib.ingame_python.commands.html b/docs/0.9.5/api/evennia.contrib.ingame_python.commands.html
index b88bdbfca9..bb06c69553 100644
--- a/docs/0.9.5/api/evennia.contrib.ingame_python.commands.html
+++ b/docs/0.9.5/api/evennia.contrib.ingame_python.commands.html
@@ -54,7 +54,7 @@
diff --git a/docs/0.9.5/api/evennia.contrib.rpsystem.html b/docs/0.9.5/api/evennia.contrib.rpsystem.html
index 9855c49ce1..e6d1f41232 100644
--- a/docs/0.9.5/api/evennia.contrib.rpsystem.html
+++ b/docs/0.9.5/api/evennia.contrib.rpsystem.html
@@ -775,7 +775,7 @@ Using the command without arguments will list all current recogs.
diff --git a/docs/0.9.5/api/evennia.contrib.tutorial_examples.cmdset_red_button.html b/docs/0.9.5/api/evennia.contrib.tutorial_examples.cmdset_red_button.html
index f264d71879..2373796da3 100644
--- a/docs/0.9.5/api/evennia.contrib.tutorial_examples.cmdset_red_button.html
+++ b/docs/0.9.5/api/evennia.contrib.tutorial_examples.cmdset_red_button.html
@@ -107,7 +107,7 @@ push the lid of the button away.
+aliases = ['push', 'press', 'press button']¶
@@ -155,7 +155,7 @@ lid-state respectively.
+aliases = ['smash', 'smash lid', 'break lid']¶
@@ -284,7 +284,7 @@ of causing the lamp to break.
+aliases = ['l', 'get', 'listen', 'ex', 'examine', 'feel']¶
diff --git a/docs/0.9.5/api/evennia.contrib.tutorial_world.objects.html b/docs/0.9.5/api/evennia.contrib.tutorial_world.objects.html
index 6385a225cc..2f3e80238c 100644
--- a/docs/0.9.5/api/evennia.contrib.tutorial_world.objects.html
+++ b/docs/0.9.5/api/evennia.contrib.tutorial_world.objects.html
@@ -353,7 +353,7 @@ of the object. We overload it with our own version.
@@ -479,7 +479,7 @@ shift green root up/down
@@ -527,7 +527,7 @@ yellow/green - horizontal roots
-
-
aliases = ['press button', 'button', 'push button']¶
+aliases = ['button', 'push button', 'press button']¶
@@ -692,7 +692,7 @@ parry - forgoes your attack but will make you harder to hit on next
-
-
aliases = ['kill', 'pierce', 'hit', 'bash', 'slash', 'parry', 'stab', 'defend', 'chop', 'fight', 'thrust']¶
+aliases = ['slash', 'defend', 'chop', 'thrust', 'parry', 'fight', 'stab', 'hit', 'bash', 'kill', 'pierce']¶
diff --git a/docs/0.9.5/api/evennia.contrib.tutorial_world.rooms.html b/docs/0.9.5/api/evennia.contrib.tutorial_world.rooms.html
index 40ecc2c00b..e3bed263a5 100644
--- a/docs/0.9.5/api/evennia.contrib.tutorial_world.rooms.html
+++ b/docs/0.9.5/api/evennia.contrib.tutorial_world.rooms.html
@@ -822,7 +822,7 @@ to find something.
-
-
aliases = ['feel around', 'search', 'l', 'feel', 'fiddle']¶
+aliases = ['feel around', 'l', 'fiddle', 'search', 'feel']¶
diff --git a/docs/0.9.5/api/evennia.utils.eveditor.html b/docs/0.9.5/api/evennia.utils.eveditor.html
index 17d8ca173a..4b224cac34 100644
--- a/docs/0.9.5/api/evennia.utils.eveditor.html
+++ b/docs/0.9.5/api/evennia.utils.eveditor.html
@@ -267,7 +267,7 @@ indentation.
-
-
aliases = [':fi', ':y', ':::', ':I', ':p', ':r', ':fd', ':w', ':dw', ':UU', ':DD', ':j', ':f', ':dd', ':!', ':i', ':h', ':=', ':S', ':echo', ':s', ':uu', ':q', ':<', ':u', ':>', ':', ':A', ':q!', ':x', ':wq', '::']¶
+aliases = [':echo', '::', ':s', ':=', ':q', ':j', ':dd', ':wq', ':w', ':', ':DD', ':r', ':UU', ':h', ':fd', ':S', ':q!', ':>', ':I', ':u', ':!', ':x', ':y', ':i', ':f', ':uu', ':dw', ':p', ':fi', ':::', ':A', ':<']¶
diff --git a/docs/0.9.5/api/evennia.utils.evmore.html b/docs/0.9.5/api/evennia.utils.evmore.html
index 69a53a0226..7c4053015e 100644
--- a/docs/0.9.5/api/evennia.utils.evmore.html
+++ b/docs/0.9.5/api/evennia.utils.evmore.html
@@ -77,7 +77,7 @@ the caller.msg() construct every time the page is updated.
-
-
aliases = ['n', 'end', 'quit', 'e', 'abort', 'b', 'a', 'q', 't', 'back', 'next', 'top']¶
+aliases = ['next', 'b', 'top', 'abort', 'n', 'quit', 'e', 'back', 'end', 'a', 't', 'q']¶
diff --git a/docs/1.0-dev/.buildinfo b/docs/1.0-dev/.buildinfo
index 9efe9fcc7f..3d14e0819f 100644
--- a/docs/1.0-dev/.buildinfo
+++ b/docs/1.0-dev/.buildinfo
@@ -1,4 +1,4 @@
# Sphinx build info version 1
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
-config: 0633c4e6f99716d16088a05549b3bd0c
+config: 400506d500dae7a94d889bdeb2b27f17
tags: 645f666f9bcd5a90fca523b33c5a78b7
diff --git a/docs/1.0-dev/Coding/Changelog.html b/docs/1.0-dev/Coding/Changelog.html
index b5ca56dd02..e53d73db1b 100644
--- a/docs/1.0-dev/Coding/Changelog.html
+++ b/docs/1.0-dev/Coding/Changelog.html
@@ -210,6 +210,14 @@ warning when using reset mode.
Attribute storage support defaultdics (Hendher)
Add ObjectParent mixin to default game folder template as an easy, ready-made
way to override features on all ObjectDB-inheriting objects easily.
+Add TagProperty, AliasProperty and PermissionProperty to assign these
+data in a similar way to django fields.
+The db pickle-serializer now checks for methods __serialize_dbobjs__ and __deserialize_dbobjs__
+to allow custom packing/unpacking of nested dbobjs, to allow storing in Attribute.
+Optimizations to rpsystem contrib performance. Breaking change: .get_sdesc() will
+now return None instead of .db.desc if no sdesc is set; fallback in hook (inspectorCaracal)
+Reworked text2html parser to avoid problems with stateful color tags (inspectorCaracal)
+Simplified EvMenu.options_formatter hook to use EvColumn and f-strings (inspectorcaracal)
diff --git a/docs/1.0-dev/Components/Attributes.html b/docs/1.0-dev/Components/Attributes.html
index e5c33c5f16..de9fb45e16 100644
--- a/docs/1.0-dev/Components/Attributes.html
+++ b/docs/1.0-dev/Components/Attributes.html
@@ -56,22 +56,35 @@
-In-code¶
-obj.db.foo = [1,2,3, "bar"]
+In-code, using the .db wrapper¶
+obj.db.foo = [1, 2, 3, "bar"]
value = obj.db.foo
-
-obj.attributes.add("myattr", 1234, category="bar")
+
+
+
+
+In-code, using the .attributes handler¶
+obj.attributes.add("myattr", 1234, category="bar")
value = attributes.get("myattr", category="bar")
-Attributes allow you to to store arbitrary data on objects and make sure the data survives a
-server reboot. An Attribute can store pretty much any
+
+In-code, using AttributeProperty at class level¶
+from evennia import DefaultObject
+from evennia import AttributeProperty
+
+class MyObject(DefaultObject):
+ foo = AttributeProperty(default=[1, 2, 3, "bar"])
+ myattr = AttributeProperty(100, category='bar')
+
+
+
+Attributes allow you to to store arbitrary data on objects and make sure the data survives a server reboot. An Attribute can store pretty much any
Python data structure and data type, like numbers, strings, lists, dicts etc. You can also
store (references to) database objects like characters and rooms.
-What can be stored in an Attribute is a must-read
-also for experienced developers, to avoid getting surprised. Attributes can store almost everything
+
What can be stored in an Attribute is a must-read to avoid being surprised, also for experienced developers. Attributes can store almost everything
but you need to know the quirks.
NAttributes are the in-memory, non-persistent
siblings of Attributes.
@@ -81,7 +94,7 @@ siblings of Attributes.
Managing Attributes in Code¶
Attributes are usually handled in code. All Typeclassed entities
(Accounts, Objects, Scripts and
-Channels) all can (and usually do) have Attributes associated with them. There
+Channels) can (and usually do) have Attributes associated with them. There
are three ways to manage Attributes, all of which can be mixed.
@@ -90,8 +103,8 @@ are three ways to manage Attributes, all of which can be mixed.
Using .db¶
-The simplest way to get/set Attributes is to use the .db shortcut:
-import evennia
+The simplest way to get/set Attributes is to use the .db shortcut. This allows for setting and getting Attributes that lack a category (having category None)
+import evennia
obj = evennia.create_object(key="Foo")
@@ -104,10 +117,10 @@ are three ways to manage Attributes, all of which can be mixed.
rose = evennia.search_object(key="rose")[0] # returns a list, grab 0th element
rose.db.has_thorns = True
-# retrieving
+# retrieving
val1 = obj.db.foo1
val2 = obj.db.foo2
-weap = obj.db.weapon
+weap = obj.db.weapon
myself = obj.db.self_reference # retrieve reference from db, get object back
is_ouch = rose.db.has_thorns
@@ -115,8 +128,8 @@ are three ways to manage Attributes, all of which can be mixed.
# this will return None, not AttributeError!
not_found = obj.db.jiwjpowiwwerw
-# returns all Attributes on the object
-obj.db.all
+# returns all Attributes on the object
+obj.db.all
# delete an Attribute
del obj.db.foo2
@@ -129,11 +142,10 @@ default all<
Using .attributes¶
-If you don’t know the name of the Attribute beforehand you can also use
-the AttributeHandler, available as .attributes. With no extra keywords this is identical
-to using the .db shortcut (.db is actually using the AttributeHandler internally):
-is_ouch = rose.attributes.get("has_thorns")
-
+If you want to group your Attribute in a category, or don’t know the name of the Attribute beforehand, you can make use of
+the AttributeHandler, available as .attributes on all typeclassed entities. With no extra keywords, this is identical to using the .db shortcut (.db is actually using the AttributeHandler internally):
+is_ouch = rose.attributes.get("has_thorns")
+
obj.attributes.add("helmet", "Knight's helmet")
helmet = obj.attributes.get("helmet")
@@ -141,8 +153,7 @@ to using the .dbobj.attributes.add("my game log", "long text about ...")
-With the AttributeHandler you can also give Attributes a category. By using a category you can
-separate same-named Attributes on the same object which can help organization:
+By using a category you can separate same-named Attributes on the same object to help organization.
# store (let's say we have gold_necklace and ringmail_armor from before)
obj.attributes.add("neck", gold_necklace, category="clothing")
obj.attributes.add("neck", ringmail_armor, category="armor")
@@ -152,12 +163,7 @@ separate same-named Attributes on the same object which can help organization:
neck_armor = obj.attributes.get("neck", category="armor")
-If you don’t specify a category, the Attribute’s category will be None. Note that
-None is also considered a category of its own, so you won’t find None-category Attributes mixed
-with Attributes having categories.
-
-When using .db, you will always use the None category.
-
+If you don’t specify a category, the Attribute’s category will be None and can thus also be found via .db. None is considered a category of its own, so you won’t find None-category Attributes mixed with Attributes having categories.
Here are the methods of the AttributeHandler. See
the AttributeHandler API for more details.
@@ -178,28 +184,27 @@ before performing the deletion. -
Examples:
try:
- # raise error if Attribute foo does not exist
+ # raise error if Attribute foo does not exist
val = obj.attributes.get("foo", raise_exception=True):
except AttributeError:
# ...
-
+
# return default value if foo2 doesn't exist
-val2 = obj.attributes.get("foo2", default=[1, 2, 3, "bar"])
+val2 = obj.attributes.get("foo2", default=[1, 2, 3, "bar"])
# delete foo if it exists (will silently fail if unset, unless
# raise_exception is set)
obj.attributes.remove("foo")
-
+
# view all clothes on obj
-all_clothes = obj.attributes.all(category="clothes")
+all_clothes = obj.attributes.all(category="clothes")
Using AttributeProperty¶
-There is a third way to set up an Attribute, and that is by setting up an AttributeProperty. This
-is done on the class level of your typeclass and allows you to treat Attributes a bit like Django
-database Fields.
+The third way to set up an Attribute is to use an AttributeProperty. This
+is done on the class level of your typeclass and allows you to treat Attributes a bit like Django database Fields. Unlike using .db and .attributes, an AttributeProperty can’t be created on the fly, you must assign it in the class code.
# mygame/typeclasses/characters.py
from evennia import DefaultCharacter
@@ -207,126 +212,55 @@ database Fields.
class Character(DefaultCharacter):
- strength = AttributeProperty(default=10, category='stat', autocreate=True)
- constitution = AttributeProperty(default=10, category='stat', autocreate=True)
- agility = AttributeProperty(default=10, category='stat', autocreate=True)
- magic = AttributeProperty(default=10, category='stat', autocreate=True)
-
- sleepy = AttributeProperty(default=False)
- poisoned = AttributeProperty(default=False)
-
- def at_object_creation(self):
- # ...
-
-
-These “Attribute-properties” will be made available to all instances of the class.
-
-Important
-If you change the default of an AttributeProperty (and reload), it will
-change the default for all instances of that class (it will not override
-explicitly changed values).
-
-char = evennia.search_object(Character, key="Bob")[0] # returns list, get 0th element
-
-# get defaults
-strength = char.strength # will get the default value 10
-
-# assign new values (this will create/update new Attributes)
-char.strength = 12
-char.constitution = 16
-char.agility = 8
-char.magic = 2
-
-# you can also do arithmetic etc
-char.magic += 2 # char.magic is now 4
-
-# check Attributes
-strength = char.strength # this is now 12
-is_sleepy = char.sleepy
-is_poisoned = char.poisoned
-
-del char.strength # wipes the Attribute
-strength = char.strengh # back to the default (10) again
-
-
-See the AttributeProperty docs for more
-details on arguments.
-An AttributeProperty will not create an Attribute by default. A new Attribute will be created
-(or an existing one retrieved/updated) will happen differently depending on how the autocreate
-keyword:
-
-If autocreate=False (default), an Attribute will be created only if the field is explicitly
-assigned a value (even if the value is the same as the default, such as char.strength = 10).
-If autocreate=True, an Attribute will be created as soon as the field is accessed in
-any way (So both strength = char.strength and char.strength = 10 will both make sure that
-an Attribute exists.
-
-Example:
-# in mygame/typeclasses/objects.py
-
-from evennia import create_object
-from evennia import DefaultObject
-from evennia.typeclasses.attributes import AttributeProperty
-
-class Object(DefaultObject):
-
- value_a = AttributeProperty(default="foo")
- value_b = AttributeProperty(default="bar", autocreate=True)
-
-obj = evennia.create_object(key="Dummy")
-
-# these will find NO Attributes!
-obj.db.value_a
-obj.attributes.get("value_a")
-obj.db.value_b
-obj.attributes.get("value_b")
-
-# get data from attribute-properties
-vala = obj.value_a # returns "foo"
-valb = obj.value_b # return "bar" AND creates the Attribute (autocreate)
-
-# the autocreate property will now be found
-obj.db.value_a # still not found
-obj.attributes.get("value_a") # ''
-obj.db.value_b # now returns "bar"
-obj.attributes.get("value_b") # ''
-
-# assign new values
-obj.value_a = 10 # will now create a new Attribute
-obj.value_b = 12 # will update the existing Attribute
-
-# both are now found as Attributes
-obj.db.value_a # now returns 10
-obj.attributes.get("value_a") # ''
-obj.db.value_b # now returns 12
-obj.attributes.get("value_b") # ''
-
-
-If you always access your Attributes via the AttributeProperty this does not matter that much
-(it’s also a bit of an optimization to not create an actual database Attribute unless the value changed).
-But until an Attribute has been created, AttributeProperty fields will not show up with the
-examine command or by using the .db or .attributes handlers - so this is a bit inconsistent.
-If this is important, you need to ‘initialize’ them by accessing them at least once … something
-like this:
-# ...
-class Character(DefaultCharacter):
-
- strength = AttributeProperty(12, autocreate=True)
- agility = AttributeProperty(12, autocreate=True)
+ strength = AttributeProperty(10, category='stat')
+ constitution = AttributeProperty(11, category='stat')
+ agility = AttributeProperty(12, category='stat')
+ magic = AttributeProperty(13, category='stat')
+ sleepy = AttributeProperty(False, autocreate=False)
+ poisoned = AttributeProperty(False, autocreate=False)
def at_object_creation(self):
- # initializing
- self.strength # by accessing it, the Attribute is auto-created
- self.agility # ''
+ # ...
-
-Important
-If you created your AttributeProperty with a category, you must specify the
-category in .attributes.get() if you want to find it this way. Remember that
-.db always uses a category of None.
+When a new instance of the class is created, new Attributes will be created with the value and category given.
+With AttributeProperty’s set up like this, one can access the underlying Attribute like a regular property on the created object:
+char = create_object(Character)
+
+char.strength # returns 10
+char.agility = 15 # assign a new value (category remains 'stat')
+
+char.db.magic # returns None (wrong category)
+char.attributes.get("agility", category="stat") # returns 15
+
+char.db.sleepy # returns None because autocreate=False (see below)
+
+
+
+Warning
+Be careful to not assign AttributeProperty’s to names of properties and methods already existing on the class, like ‘key’ or ‘at_object_creation’. That could lead to very confusing errors.
+
+The autocreate=False (default is True) used for sleepy and poisoned is worth a closer explanation. When False, no Attribute will be auto-created for these AttributProperties unless they are explicitly set.
+The advantage of not creating an Attribute is that the default value given to AttributeProperty is returned with no database access unless you change it. This also means that if you want to change the default later, all entities previously create will inherit the new default.
+The drawback is that without a database precense you can’t find the Attribute via .db and .attributes.get (or by querying for it in other ways in the database):
+char.sleepy # returns False, no db access
+
+char.db.sleepy # returns None - no Attribute exists
+char.attributes.get("sleepy") # returns None too
+
+char.sleepy = True # now an Attribute is created
+char.db.sleepy # now returns True!
+char.attributes.get("sleepy") # now returns True
+
+char.sleepy # now returns True, involves db access
+
+
+
+You can e.g. del char.strength to set the value back to the default (the value defined
+in the AttributeProperty).
+See the AttributeProperty API for more details on how to create it with special options, like giving access-restrictions.
@@ -342,7 +276,7 @@ problem.
To view, do
-set myobj/foo
+set myobj/foo
or see them together with all object-info with
@@ -424,16 +358,16 @@ values into a string representation before storing it to the database. This is d
With a single object, we mean anything that is not iterable, like numbers, strings or custom class
instances without the __iter__ method.
-You can generally store any non-iterable Python entity that can be pickled.
+You can generally store any non-iterable Python entity that can be pickled.
Single database objects/typeclasses can be stored, despite them normally not being possible
-to pickle. Evennia wil convert them to an internal representation using their classname,
+to pickle. Evennia will convert them to an internal representation using theihr classname,
database-id and creation-date with a microsecond precision. When retrieving, the object
instance will be re-fetched from the database using this information.
-To convert the database object, Evennia must know it’s there. If you hide a database object
-inside a non-iterable class, you will run into errors - this is not supported!
+If you ‘hide’ a db-obj as a property on a custom class, Evennia will not be
+able to find it to serialize it. For that you need to help it out (see below).
-
-Valid assignments¶
+
+Valid assignments¶
# Examples of valid single-value attribute data:
obj.db.test1 = 23
obj.db.test1 = False
@@ -442,15 +376,51 @@ inside a non-iterable class, you will run into errors - this is not supported!
-
-Invalid, ‘hidden’ dbobject¶
-# example of an invalid, "hidden" dbobject
+As mentioned, Evennia will not be able to automatically serialize db-objects
+‘hidden’ in arbitrary properties on an object. This will lead to an error
+when saving the Attribute.
+
+Invalid, ‘hidden’ dbobject¶
+# example of storing an invalid, "hidden" dbobject in Attribute
class Container:
def __init__(self, mydbobj):
# no way for Evennia to know this is a database object!
self.mydbobj = mydbobj
+
+# let's assume myobj is a db-object
container = Container(myobj)
-obj.db.invalid = container # will cause error!
+obj.db.mydata = container # will raise error!
+
+
+
+By adding two methods __serialize_dbobjs__ and __deserialize_dbobjs__ to the
+object you want to save, you can pre-serialize and post-deserialize all ‘hidden’
+objects before Evennia’s main serializer gets to work. Inside these methods, use Evennia’s
+evennia.utils.dbserialize.dbserialize and
+dbunserialize functions to safely
+serialize the db-objects you want to store.
+
+Fixing an invalid ‘hidden’ dbobj for storing in Attribute¶
+from evennia.utils import dbserialize # important
+
+class Container:
+ def __init__(self, mydbobj):
+ # A 'hidden' db-object
+ self.mydbobj = mydbobj
+
+ def __serialize_dbobjs__(self):
+ """This is called before serialization and allows
+ us to custom-handle those 'hidden' dbobjs"""
+ self.mydbobj = dbserialize.dbserialize(self.mydbobj
+
+ def __deserialize_dbobjs__(self):
+ """This is called after deserialization and allows you to
+ restore the 'hidden' dbobjs you serialized before"""
+ self.mydbobj = dbserialize.dbunserialize(self.mydbobj)
+
+# let's assume myobj is a db-object
+container = Container(myobj)
+obj.db.mydata = container # will now work fine!
@@ -499,6 +469,10 @@ process but for efficiency you may want to avoid too deeply nested structures if
# test8 is now [4,2,{"test":5}]
+Note that if make some advanced iterable object, and store an db-object on it in
+a way such that it is not returned by iterating over it, you have created a
+‘hidden’ db-object. See the previous section for how
+to tell Evennia how to serialize such hidden objects safely.
Retrieving Mutable objects¶
@@ -525,14 +499,14 @@ variable, e.g. myli
of the variable. If you update the snapshot, it will save to the database, but this change will not propagate to
any other snapshots you may have done previously.
obj.db.mylist = [1, 2, 3, 4]
-mylist1 = obj.db.mylist
-mylist2 = obj.db.mylist
-mylist1[3] = 5
+mylist1 = obj.db.mylist
+mylist2 = obj.db.mylist
+mylist1[3] = 5
print(mylist1) # this is now [1, 2, 3, 5]
-print(obj.db.mylist) # also updated to [1, 2, 3, 5]
+print(obj.db.mylist) # also updated to [1, 2, 3, 5]
-print(mylist2) # still [1, 2, 3, 4] !
+print(mylist2) # still [1, 2, 3, 4] !
@@ -546,7 +520,7 @@ back the results as needed.
You can also choose to “disconnect” the Attribute entirely from the
database with the help of the .deserialize() method:
obj.db.mylist = [1, 2, 3, 4, {1: 2}]
-mylist = obj.db.mylist.deserialize()
+mylist = obj.db.mylist.deserialize()
The result of this operation will be a structure only consisting of normal Python mutables (list
diff --git a/docs/1.0-dev/Components/FuncParser.html b/docs/1.0-dev/Components/FuncParser.html
index 1aac9fab80..2be93c87b0 100644
--- a/docs/1.0-dev/Components/FuncParser.html
+++ b/docs/1.0-dev/Components/FuncParser.html
@@ -57,15 +57,16 @@ the return from the function.
from evennia.utils.funcparser import FuncParser
def _power_callable(*args, **kwargs):
- """This will be callable as $square(number, power=<num>) in string"""
+ """This will be callable as $pow(number, power=<num>) in string"""
pow = int(kwargs.get('power', 2))
return float(args[0]) ** pow
+# create a parser and tell it that '$pow' means using _power_callable
parser = FuncParser({"pow": _power_callable})
-Next, just pass a string into the parser, optionally containing $func(...) markers:
+Next, just pass a string into the parser, containing $func(...) markers:
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."
@@ -111,7 +112,7 @@ Evennia expects you to do in a proper text editor, outside of the game, not from
from evennia.utils import funcparser
parser = FuncParser(callables, **default_kwargs)
-parsed_string = parser.parser(input_string, raise_errors=False,
+parsed_string = parser.parse(input_string, raise_errors=False,
escape=False, strip=False,
return_str=True, **reserved_kwargs)
@@ -131,8 +132,12 @@ If no such variable is defined, every top-level function in the module
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 **default kwargs are optional kwargs that will be passed to all
+callables every time this parser is used - unless the user overrides it explicitly in
+their call. This is great for providing sensible standards that the user can
+tweak as needed.
-The other arguments to the parser:
+FuncParser.parse takes further arguments, and can vary for every string parsed.
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,
@@ -143,12 +148,14 @@ this properly.
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.
+The **reserved_keywords are always passed to every callable in the string.
+They override any **defaults given when instantiating the parser and cannot
+be overridden by the user - if they enter the same kwarg it will be ignored.
+This is great for providing the current session, settings etc.
+The funcparser and raise_errors
+are always added as reserved keywords - the first is a
+back-reference to the FuncParser instance and the second
+is the raise_errors boolean given to FuncParser.parse.
Here’s an example of using the default/reserved keywords:
def _test(*args, **kwargs):
@@ -193,7 +200,8 @@ of the string and may or may not raise the exception depending on what you set <
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.
+Python’s literal_eval and/or simple_eval. It returns whatever data type it
+evaluates to.
"There's a $toint($eval(10 * 2.2))% chance of survival."
@@ -210,21 +218,67 @@ will be a 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,
+
However, if you use the parse_to_any (or parse(..., return_str=False)) and
+don’t add any extra string around the outermost function call,
you’ll get the return type of the outermost callable back:
-parser.parse_to_any("$toint($eval(10 * 2.2)%")
-"22%"
-parser.parse_to_any("$toint($eval(10 * 2.2)")
+parser.parse_to_any("$toint($eval(10 * 2.2)")
22
+parser.parse_to_any("the number $toint($eval(10 * 2.2).")
+"the number 22"
+parser.parse_to_any("$toint($eval(10 * 2.2)%")
+"22%"
+
+Escaping special character¶
+When entering funcparser callables in strings, it looks like a regular
+function call inside a string:
+"This is a $myfunc(arg1, arg2, kwarg=foo)."
+
+
+Commas (,) and equal-signs (=) are considered to separate the arguments and
+kwargs. In the same way, the right parenthesis ()) closes the argument list.
+Sometimes you want to include commas in the argument without it breaking the
+argument list.
+"There is a $format(beautiful meadow, with dandelions) to the west."
+
+
+You can escape in various ways.
+
+Prepending with the escape character \
+ ```python
+ "There is a $format(beautiful meadow\, with dandelions) to the west."
+ ```
+
+
+
+Wrapping your strings in quotes. This works like Python, and you can nest
+double and single quotes inside each other if so needed. The result will
+be a verbatim string that contains everything but the outermost quotes.
+ ```python
+ "There is a $format('beautiful meadow, with dandelions') to the west."
+ ```
+
+
+
+If you want verbatim quotes in your string, you can escape them too.
+ ```python
+ "There is a $format('beautiful meadow, with \'dandelions\'') to the west."
+ ```
+
+
+
+
+
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.
+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 can be 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. This function
automates the conversion of simple data types in a safe way:
@@ -232,26 +286,28 @@ automates the conversion of simple data types in a safe way:
def _process_callable(*args, **kwargs):
"""
- A callable with a lot of custom options
-
- $process(expression, local, extra=34, extra2=foo)
+ $process(expression, local, extra1=34, extra2=foo)
"""
args, kwargs = safe_convert_to_type(
- (('py', 'py'), {'extra1': int, 'extra2': str}),
+ (('py', str), {'extra1': int, 'extra2': str}),
*args, **kwargs)
# args/kwargs should be correct types now
+In other words, in the callable $process(expression, local, extra1=.., extra2=...), the first argument will be handled by the ‘py’ converter
+(described below), the second will passed through regular Python str,
+kwargs will be handled by int and str respectively. You can supply
+your own converter function as long as it takes one argument and returns
+the converted result.
In other words,
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
+
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 is an in-built Python
@@ -439,6 +495,7 @@ all the defaults (like Uses in default Evennia
- Using the FuncParser
- Defining custom callables
diff --git a/docs/1.0-dev/Components/Permissions.html b/docs/1.0-dev/Components/Permissions.html
index 33de2887f4..6ef1cccf2d 100644
--- a/docs/1.0-dev/Components/Permissions.html
+++ b/docs/1.0-dev/Components/Permissions.html
@@ -62,11 +62,10 @@ hierarchies. It is set by the settings.PERMISSION_ACCOUNT_DEFAULT.
Managing Permissions¶
-In-game, you use the perm command to add and remove permissions
- perm/account Tommy = Builders
- perm/account/del Tommy = Builders
-
-
+In-game, you use the perm command to add and remove permissions
+j
+perm/account Tommy = Builders
+perm/account/del Tommy = Builders
Note the use of the /account switch. It means you assign the permission to the
Accounts Tommy instead of any Character that also
happens to be named “Tommy”.
diff --git a/docs/1.0-dev/Components/Tags.html b/docs/1.0-dev/Components/Tags.html
index 43eb566ec5..3c703dca67 100644
--- a/docs/1.0-dev/Components/Tags.html
+++ b/docs/1.0-dev/Components/Tags.html
@@ -49,18 +49,33 @@
Tags¶
-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, 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 to check for).
+
+In game¶
+> tag obj = tagname
+
+
+
+
+In code, using .tags (TagHandler)¶
+obj.tags.add("mytag", category="foo")
+obj.tags.get("mytag", category="foo")
+
+
+
+
+In code, using TagProperty (auto-assign tag to all instances of the class)¶
+from evennia import DefaultObject
+from evennia import TagProperty
+class Sword(DefaultObject):
+ can_be_wielded = TagProperty(category='combat')
+ has_sharp_edge = TagProperty(category='combat')
+
+
+
+Tags are short text lables one can ‘hang’ on objects in order to organize, group and quickly find out their properties. An Evennia entity can be tagged by any number of tags. They are more efficient than Attributes since on the database-side, Tags are shared between all objects with that particular tag. A tag does not carry a value in itself; it either sits on the entity
+Above, the tags inform us that the Sword is both sharp and can be wielded. If that’s all they do, they could just be a normal Python flag. When tags become important is if there are a lot of objects with different combinations of tags. Maybe you have a magical spell that dulls all sharp-edged objects in the castle - whether sword, dagger, spear or kitchen knife! You can then just grab all objects with the has_sharp_edge tag.
+Another example would be a weather script affecting all rooms tagged as outdoors or finding all characters tagged with belongs_to_fighter_guild.
+In Evennia, Tags are technically also used to implement Aliases (alternative names for objects) and Permissions (simple strings for Locks to check for).