diff --git a/docs/latest/.buildinfo b/docs/latest/.buildinfo index 9508576a45..2c7bbd3a0a 100644 --- a/docs/latest/.buildinfo +++ b/docs/latest/.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: b7f3bde8bd7f2104b246ef81cda88ee7 +config: 3d218971e6732f6d07286e28b58c83c5 tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs/latest/Coding/Changelog.html b/docs/latest/Coding/Changelog.html index 79b81a6b19..b3ec2881c8 100644 --- a/docs/latest/Coding/Changelog.html +++ b/docs/latest/Coding/Changelog.html @@ -216,6 +216,12 @@ settings (count-infinity)
findsbig sword even if another type of sword is around (InspectorCaracal)
Fix: In searches, allow special ‘here’ and ‘me’ keywords only be valid queries unless current location and/or caller is in valid search candidates respectively (InspectorCaracal)
[Fix][pull3694]: Funcparser swallowing rest of line after a \-escape (count-infinity)
Fix: Properly serialize IntFlag enum types (0xDEADFED5)
Fix: Correct links in about command (0xDEADFED5)
Fix: Clean reduntant session clearin in at_server_cold_start (InspectorCaracal)
Fix: Usability improvements in the Discord integration (InspectorCaracal)
Fix: Make \\ properly preserve one backlash in funcparser (Griatch)
[Docs]: Fixes from InspectorCaracal, Griatch
Find the point in the code where you want to have more insight. Add the following line at that point.
-from evennia import set_trace;set_trace()
+from evennia import set_trace;set_trace()
@@ -164,7 +164,7 @@ default cmdset. Then restart Evennia in interactive mode with # In file commands/command.py
-class CmdTest(Command):
+class CmdTest(Command):
"""
A test command just to test pdb.
@@ -176,8 +176,8 @@ default cmdset. Then restart Evennia in interactive mode with key = "test"
- def func(self):
- from evennia import set_trace; set_trace() # <--- start of debugger
+ def func(self):
+ from evennia import set_trace; set_trace() # <--- start of debugger
obj = self.search(self.args)
self.msg("You've found {}.".format(obj.get_display_name()))
@@ -199,8 +199,8 @@ default cmdset. Then restart Evennia in interactive mode with 43
44 key = "test"
45
- 46 def func(self):
- 47 from evennia import set_trace; set_trace() # <--- start of debugger
+ 46 def func(self):
+ 47 from evennia import set_trace; set_trace() # <--- start of debugger
48 -> obj = self.search(self.args)
49 self.msg("You've found {}.".format(obj.get_display_name()))
50
diff --git a/docs/latest/Coding/Evennia-Code-Style.html b/docs/latest/Coding/Evennia-Code-Style.html
index 3c5031710a..21fc8766c9 100644
--- a/docs/latest/Coding/Evennia-Code-Style.html
+++ b/docs/latest/Coding/Evennia-Code-Style.html
@@ -203,7 +203,7 @@ class. It should usually not describe the exact call sequence nor list
important methods, this tends to be hard to keep updated as the API
develops. Don’t use section markers (#, ## etc).
Example of class docstring:
-class MyClass(object):
+class MyClass(object):
"""
This class describes the creation of `Objects`. It is useful
in many situations, such as ...
@@ -216,7 +216,7 @@ develops. Don’t use section markers (¶
Example of function or method docstring:
-def funcname(a, b, c, d=False, **kwargs):
+def funcname(a, b, c, d=False, **kwargs):
"""
This is a brief introduction to the function/class/method
diff --git a/docs/latest/Coding/Profiling.html b/docs/latest/Coding/Profiling.html
index a0a07bef12..de42b370d3 100644
--- a/docs/latest/Coding/Profiling.html
+++ b/docs/latest/Coding/Profiling.html
@@ -143,7 +143,7 @@
Python’s timeit module is very good for testing small things. For example, in
order to test if it is faster to use a for loop or a list comprehension you
could use the following code:
- import timeit
+ import timeit
# Time to do 1000000 for loops
timeit.timeit("for i in range(100):\n a.append(i)", setup="a = []")
<<< 10.70982813835144
@@ -174,8 +174,8 @@ could use the following code:
Then in the shell
-import pstats
-from pstats import SortKey
+import pstats
+from pstats import SortKey
p = pstats.Stats('server/log/server.prof')
p.strip_dirs().sort_stats(-1).print_stats()
@@ -260,7 +260,7 @@ be able to connect with an existing user since the password hasher chan
# actions
-def c_login(client):
+def c_login(client):
name = f"Character-{client.gid}"
pwd = f"23fwsf23sdfw23wef23"
return (
@@ -268,10 +268,10 @@ be able to connect with an existing user since the password hasher chan
f"connect {name} {pwd}"
)
-def c_logout(client):
+def c_logout(client):
return ("quit", )
-def c_look(client):
+def c_look(client):
return ("look here", "look me")
# this is read by dummyrunner.
diff --git a/docs/latest/Coding/Unit-Testing.html b/docs/latest/Coding/Unit-Testing.html
index 68180a3d35..cc60a770a5 100644
--- a/docs/latest/Coding/Unit-Testing.html
+++ b/docs/latest/Coding/Unit-Testing.html
@@ -188,31 +188,31 @@ are two special, optional methods Here’s an example of the principle. Let’s assume you put this in mygame/world/tests.py
and want to test a function in mygame/world/myfunctions.py
# in a module tests.py somewhere i your game dir
- import unittest
+ import unittest
- from evennia import create_object
+ from evennia import create_object
# the function we want to test
- from .myfunctions import myfunc
+ from .myfunctions import myfunc
- class TestObj(unittest.TestCase):
+ class TestObj(unittest.TestCase):
"This tests a function myfunc."
- def setUp(self):
+ def setUp(self):
"""done before every of the test_ * methods below"""
self.obj = create_object("mytestobject")
- def tearDown(self):
+ def tearDown(self):
"""done after every test_* method below """
self.obj.delete()
- def test_return_value(self):
+ def test_return_value(self):
"""test method. Makes sure return value is as expected."""
actual_return = myfunc(self.obj)
expected_return = "This is the good object 'mytestobject'."
# test
self.assertEqual(expected_return, actual_return)
- def test_alternative_call(self):
+ def test_alternative_call(self):
"""test method. Calls with a keyword argument."""
actual_return = myfunc(self.obj, bad=True)
expected_return = "This is the baaad object 'mytestobject'."
@@ -278,32 +278,32 @@ just there for naming symmetry with <
Here’s an example of using EvenniaTest
# in a test module
-from evennia.utils.test_resources import EvenniaTest
+from evennia.utils.test_resources import EvenniaTest
-class TestObject(EvenniaTest):
+class TestObject(EvenniaTest):
"""Remember that the testing class creates char1 and char2 inside room1 ..."""
- def test_object_search_character(self):
+ def test_object_search_character(self):
"""Check that char1 can search for char2 by name"""
self.assertEqual(self.char1.search(self.char2.key), self.char2)
- def test_location_search(self):
+ def test_location_search(self):
"""Check so that char1 can find the current location by name"""
self.assertEqual(self.char1.search(self.char1.location.key), self.char1.location)
# ...
This example tests a custom command.
- from evennia.commands.default.tests import EvenniaCommandTest
-from commands import command as mycommand
+ from evennia.commands.default.tests import EvenniaCommandTest
+from commands import command as mycommand
-class TestSet(EvenniaCommandTest):
+class TestSet(EvenniaCommandTest):
"tests the look command by simple call, using Char2 as a target"
- def test_mycmd_char(self):
+ def test_mycmd_char(self):
self.call(mycommand.CmdMyLook(), "Char2", "Char2(#7)")
- def test_mycmd_room(self):
+ def test_mycmd_room(self):
"tests the look command by simple call, with target as room"
self.call(mycommand.CmdMyLook(), "Room",
"Room(#1)\nroom_desc\nExits: out(#3)\n"
@@ -353,9 +353,9 @@ of the Evennia distribution and its unit tests should be run with all other Even
# a file contrib/mycontrib/tests.py
-from django.conf import settings
-import django
-from evennia.utils.test_resources import BaseEvenniaTest
+from django.conf import settings
+import django
+from evennia.utils.test_resources import BaseEvenniaTest
OLD_DEFAULT_SETTINGS = settings.INSTALLED_APPS
DEFAULT_SETTINGS = dict(
@@ -371,29 +371,29 @@ of the Evennia distribution and its unit tests should be run with all other Even
)
-class TestMyModel(BaseEvenniaTest):
- def setUp(self):
+class TestMyModel(BaseEvenniaTest):
+ def setUp(self):
if not settings.configured:
settings.configure(**DEFAULT_SETTINGS)
django.setup()
- from django.core.management import call_command
- from django.db.models import loading
+ from django.core.management import call_command
+ from django.db.models import loading
loading.cache.loaded = False
call_command('syncdb', verbosity=0)
- def tearDown(self):
+ def tearDown(self):
settings.configure(**OLD_DEFAULT_SETTINGS)
django.setup()
- from django.core.management import call_command
- from django.db.models import loading
+ from django.core.management import call_command
+ from django.db.models import loading
loading.cache.loaded = False
call_command('syncdb', verbosity=0)
# test cases below ...
- def test_case(self):
+ def test_case(self):
# test case here
diff --git a/docs/latest/Components/Accounts.html b/docs/latest/Components/Accounts.html
index 3fcdc1724f..2a9472e57a 100644
--- a/docs/latest/Components/Accounts.html
+++ b/docs/latest/Components/Accounts.html
@@ -151,11 +151,11 @@ Evennia’s MULTISESSION_MODE
Here’s an example of modifying the default Account class in code:
# in mygame/typeclasses/accounts.py
- from evennia import DefaultAccount
+ from evennia import DefaultAccount
- class Account(DefaultAccount):
+ class Account(DefaultAccount):
# [...]
- def at_account_creation(self):
+ def at_account_creation(self):
"this is called only once, when account is first created"
self.db.real_name = None # this is set later
self.db.real_address = None # "
diff --git a/docs/latest/Components/Attributes.html b/docs/latest/Components/Attributes.html
index 7b85b01ee7..0820dd6c6d 100644
--- a/docs/latest/Components/Attributes.html
+++ b/docs/latest/Components/Attributes.html
@@ -161,10 +161,10 @@
In-code, using AttributeProperty at class level¶
-from evennia import DefaultObject
-from evennia import AttributeProperty
+from evennia import DefaultObject
+from evennia import AttributeProperty
-class MyObject(DefaultObject):
+class MyObject(DefaultObject):
foo = AttributeProperty(default=[1, 2, 3, "bar"])
myattr = AttributeProperty(100, category='bar')
@@ -177,7 +177,7 @@
Using .db¶
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
+import evennia
obj = evennia.create_object(key="Foo")
@@ -265,10 +265,10 @@
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
-from evennia.typeclasses.attributes import AttributeProperty
+from evennia import DefaultCharacter
+from evennia.typeclasses.attributes import AttributeProperty
-class Character(DefaultCharacter):
+class Character(DefaultCharacter):
strength = AttributeProperty(10, category='stat')
constitution = AttributeProperty(11, category='stat')
@@ -278,7 +278,7 @@
sleepy = AttributeProperty(False, autocreate=False)
poisoned = AttributeProperty(False, autocreate=False)
- def at_object_creation(self):
+ def at_object_creation(self):
# ...
@@ -449,8 +449,8 @@ set mypobj/mystring = [1, 2, foo] # foo is invalid Python (no quotes)
Invalid, ‘hidden’ dbobject¶
# example of storing an invalid, "hidden" dbobject in Attribute
-class Container:
- def __init__(self, mydbobj):
+class Container:
+ def __init__(self, mydbobj):
# no way for Evennia to know this is a database object!
self.mydbobj = mydbobj
@@ -463,19 +463,19 @@ set mypobj/mystring = [1, 2, foo] # foo is invalid Python (no quotes)
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
+from evennia.utils import dbserialize # important
-class Container:
- def __init__(self, mydbobj):
+class Container:
+ def __init__(self, mydbobj):
# A 'hidden' db-object
self.mydbobj = mydbobj
- def __serialize_dbobjs__(self):
+ 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):
+ def __deserialize_dbobjs__(self):
"""This is called after deserialization and allows you to
restore the 'hidden' dbobjs you serialized before"""
if isinstance(self.mydbobj, bytes):
diff --git a/docs/latest/Components/Batch-Code-Processor.html b/docs/latest/Components/Batch-Code-Processor.html
index 527d18406e..4c864d34c0 100644
--- a/docs/latest/Components/Batch-Code-Processor.html
+++ b/docs/latest/Components/Batch-Code-Processor.html
@@ -163,9 +163,9 @@
# This will be included in all other #CODE blocks
- from evennia import create_object, search_object
- from evennia.contrib.tutorial_examples import red_button
- from typeclasses.objects import Object
+ from evennia import create_object, search_object
+ from evennia.contrib.tutorial_examples import red_button
+ from typeclasses.objects import Object
limbo = search_object('Limbo')[0]
@@ -217,9 +217,9 @@
This shows that you are on the first #CODE block, the first of only two commands in this batch file. Observe that the block has not actually been executed at this point!
To take a look at the full code snippet you are about to run, use ll (a batch-processor version of look).
- from evennia.utils import create, search
- from evennia.contrib.tutorial_examples import red_button
- from typeclasses.objects import Object
+ from evennia.utils import create, search
+ from evennia.contrib.tutorial_examples import red_button
+ from typeclasses.objects import Object
limbo = search.objects(caller, 'Limbo', global_search=True)[0]
diff --git a/docs/latest/Components/Channels.html b/docs/latest/Components/Channels.html
index f56feb1e02..eeee9188f3 100644
--- a/docs/latest/Components/Channels.html
+++ b/docs/latest/Components/Channels.html
@@ -338,9 +338,9 @@ will still only be able to admin or destroy channels they actually control!
channels you could override the help command and change the lockstring to:
# in for example mygame/commands/commands.py
- from evennia import default_cmds
+ from evennia import default_cmds
- class MyCustomChannelCmd(default_cmds.CmdChannel):
+ class MyCustomChannelCmd(default_cmds.CmdChannel):
locks = "cmd: not pperm(channel_banned);admin:perm(Builder);manage:perm(Builder);changelocks:perm(Admin)"
@@ -396,8 +396,8 @@ Default channels all use To change which channel typeclass Evennia uses for default commands, change settings.BASE_CHANNEL_TYPECLASS. The base command class is evennia.comms.comms.DefaultChannel. There is an empty child class in mygame/typeclasses/channels.py, same as for other typelass-bases.
In code you create a new channel with evennia.create_channel or
Channel.create:
- from evennia import create_channel, search_object
- from typeclasses.channels import Channel
+ from evennia import create_channel, search_object
+ from typeclasses.channels import Channel
channel = create_channel("my channel", aliases=["mychan"], locks=..., typeclass=...)
# alternative
diff --git a/docs/latest/Components/Coding-Utils.html b/docs/latest/Components/Coding-Utils.html
index 3cb3172c46..bf6422e556 100644
--- a/docs/latest/Components/Coding-Utils.html
+++ b/docs/latest/Components/Coding-Utils.html
@@ -155,7 +155,7 @@ on all objects. This will search for objects in the same location and inside the
Give the keyword global_search=True to extend search to encompass entire database. Aliases will also be matched by this search. You will find multiple examples of this functionality in the default command set.
If you need to search for objects in a code module you can use the functions in
evennia.utils.search. You can access these as shortcuts evennia.search_*.
- from evennia import search_object
+ from evennia import search_object
obj = search_object(objname)
@@ -173,7 +173,7 @@ on all objects. This will search for objects in the same location and inside the
Create¶
Apart from the in-game build commands (@create etc), you can also build all of Evennia’s game entities directly in code (for example when defining new create commands).
- import evennia
+ import evennia
myobj = evennia.create_objects("game.gamesrc.objects.myobj.MyObj", key="MyObj")
@@ -192,7 +192,7 @@ on all objects. This will search for objects in the same location and inside the
Logging¶
Normally you can use Python print statements to see output to the terminal/log. The print
statement should only be used for debugging though. For producion output, use the logger which will create proper logs either to terminal or to file.
- from evennia import logger
+ from evennia import logger
#
logger.log_err("This is an Error!")
logger.log_warn("This is a Warning!")
@@ -220,7 +220,7 @@ kill the server.
Game time¶
Evennia tracks the current server time. You can access this time via the evennia.gametime shortcut:
-from evennia import gametime
+from evennia import gametime
# all the functions below return times in seconds).
@@ -246,9 +246,9 @@ kill the server.
The setting TIME_FACTOR determines how fast/slow in-game time runs compared to the real world. The setting TIME_GAME_EPOCH sets the starting game epoch (in seconds). The functions from the gametime module all return their times in seconds. You can convert this to whatever units of time you desire for your game. You can use the @time command to view the server time info.
You can also schedule things to happen at specific in-game times using the gametime.schedule function:
-import evennia
+import evennia
-def church_clock:
+def church_clock:
limbo = evennia.search_object(key="Limbo")
limbo.msg_contents("The church clock chimes two.")
@@ -269,9 +269,9 @@ You can also schedule things to happen at specific in-game times using
utils.delay()¶
This allows for making a delayed call.
-from evennia import utils
+from evennia import utils
-def _callback(obj, text):
+def _callback(obj, text):
obj.msg(text)
# wait 10 seconds before sending "Echo!" to obj (which we assume is defined)
@@ -292,7 +292,7 @@ You can also schedule things to happen at specific in-game times using
will only catch immediate dependence). This function also accepts as input any combination of
classes, instances or python-paths-to-classes.
Note that Python code should usually work with duck typing. But in Evennia’s case it can sometimes be useful to check if an object inherits from a given Typeclass as a way of identification. Say for example that we have a typeclass Animal. This has a subclass Felines which in turn has a subclass HouseCat. Maybe there are a bunch of other animal types too, like horses and dogs. Using inherits_from will allow you to check for all animals in one go:
- from evennia import utils
+ from evennia import utils
if (utils.inherits_from(obj, "typeclasses.objects.animals.Animal"):
obj.msg("The bouncer stops you in the door. He says: 'No talking animals allowed.'")
diff --git a/docs/latest/Components/Command-Sets.html b/docs/latest/Components/Command-Sets.html
index 495824dda4..86556307cd 100644
--- a/docs/latest/Components/Command-Sets.html
+++ b/docs/latest/Components/Command-Sets.html
@@ -159,14 +159,14 @@ but are used for more advanced set manipulation and coding (see the [merge rules
Sets#merge-rules) section).
# file mygame/commands/mycmdset.py
-from evennia import CmdSet
+from evennia import CmdSet
# this is a theoretical custom module with commands we
# created previously: mygame/commands/mycommands.py
-from commands import mycommands
+from commands import mycommands
-class MyCmdSet(CmdSet):
- def at_cmdset_creation(self):
+class MyCmdSet(CmdSet):
+ def at_cmdset_creation(self):
"""
The only thing this method should need
to do is to add commands to the set.
@@ -178,7 +178,7 @@ Sets#merge-rules) section).
The CmdSet’s add() method can also take another CmdSet as input. In this case all the commands
from that CmdSet will be appended to this one as if you added them line by line:
- def at_cmdset_creation():
+ def at_cmdset_creation():
...
self.add(AdditionalCmdSet) # adds all command from this set
...
@@ -455,16 +455,16 @@ sure we merge onto B. Setting E’s priority to, say, -4 will make sure to merg
it appropriately.
More advanced cmdset example:
-from commands import mycommands
+from commands import mycommands
-class MyCmdSet(CmdSet):
+class MyCmdSet(CmdSet):
key = "MyCmdSet"
priority = 4
mergetype = "Replace"
key_mergetypes = {'MyOtherCmdSet':'Union'}
- def at_cmdset_creation(self):
+ def at_cmdset_creation(self):
"""
The only thing this method should need
to do is to add commands to the set.
diff --git a/docs/latest/Components/Commands.html b/docs/latest/Components/Commands.html
index 8f61c6fe96..0841b06a1c 100644
--- a/docs/latest/Components/Commands.html
+++ b/docs/latest/Components/Commands.html
@@ -160,26 +160,26 @@ Evennia actually inherit from a child of /switches, splitting by “=” etc. Below we’ll avoid mux-
specifics and use the base Command class directly.
# basic Command definition
- from evennia import Command
+ from evennia import Command
- class MyCmd(Command):
+ class MyCmd(Command):
"""
This is the help-text for the command
"""
key = "mycommand"
- def parse(self):
+ def parse(self):
# parsing the command line here
- def func(self):
+ def func(self):
# executing the command here
Here is a minimalistic command with no custom parsing:
- from evennia import Command
+ from evennia import Command
- class CmdEcho(Command):
+ class CmdEcho(Command):
key = "echo"
- def func(self):
+ def func(self):
# echo the caller's input back to the caller
self.caller.msg(f"Echo: {self.args}")
@@ -282,9 +282,9 @@ truthfully report this value - that case the doc string (__doc__) at the top of your class. This string is dynamically read by the Help System to create the help entry for this command. You should decide on a way to format your help and stick to that.
Below is how you define a simple alternative “smile” command:
-from evennia import Command
+from evennia import Command
-class CmdSmile(Command):
+class CmdSmile(Command):
"""
A smile command
@@ -305,11 +305,11 @@ truthfully report this value - that case the locks = "cmd:all()"
help_category = "General"
- def parse(self):
+ def parse(self):
"Very trivial parser"
self.target = self.args.strip()
- def func(self):
+ def func(self):
"This actually does things"
caller = self.caller
@@ -357,13 +357,13 @@ possible. Only if there is a collision, will the prefix be shown in the help sys
Exiting a command¶
Normally you just use return in one of your Command class’ hook methods to exit that method. That will however still fire the other hook methods of the Command in sequence. That’s usually what you want but sometimes it may be useful to just abort the command, for example if you find some unacceptable input in your parse method. To exit the command this way you can raise evennia.InterruptCommand:
-from evennia import InterruptCommand
+from evennia import InterruptCommand
-class MyCommand(Command):
+class MyCommand(Command):
# ...
- def parse(self):
+ def parse(self):
# ...
# if this fires, `func()` and `at_post_cmd` will not
# be called at all
@@ -383,9 +383,9 @@ the current execution of your command and wait for more before processing.
Note that you cannot just drop yield into any code and expect it to pause. Evennia will only pause for you if you yield inside the Command’s func() method. Don’t expect it to work anywhere else.
Here’s an example of a command using a small pause of five seconds between messages:
-from evennia import Command
+from evennia import Command
-class CmdWait(Command):
+class CmdWait(Command):
"""
A dummy command to show how to wait
@@ -398,7 +398,7 @@ the current execution of your command and wait for more before processing.
locks = "cmd:all()"
help_category = "General"
- def func(self):
+ def func(self):
"""Command execution."""
self.msg("Beginner-Tutorial to wait ...")
yield 5
@@ -421,7 +421,7 @@ the current execution of your command and wait for more before processing.
Here’s a very simple example:
-class CmdConfirm(Command):
+class CmdConfirm(Command):
"""
A dummy command to show confirmation.
@@ -433,7 +433,7 @@ the current execution of your command and wait for more before processing.
key = "confirm"
- def func(self):
+ def func(self):
answer = yield("Are you sure you want to go on?")
if answer.strip().lower() in ("yes", "y"):
self.msg("Yes!")
@@ -461,12 +461,12 @@ the current execution of your command and wait for more before processing.
New session connection (syscmdkeys.CMD_LOGINSTART). This command name should be put in the settings.CMDSET_UNLOGGEDIN. Whenever a new connection is established, this command is always called on the server (default is to show the login screen).
Below is an example of redefining what happens when the account doesn’t provide any input (e.g. just presses return). Of course the new system command must be added to a cmdset as well before it will work.
- from evennia import syscmdkeys, Command
+ from evennia import syscmdkeys, Command
- class MyNoInputCommand(Command):
+ class MyNoInputCommand(Command):
"Usage: Just press return, I dare you"
key = syscmdkeys.CMD_NOINPUT
- def func(self):
+ def func(self):
self.caller.msg("Don't just press return like that, talk to me!")
@@ -499,10 +499,10 @@ the current execution of your command and wait for more before processing.
Note: On a server reload, all Commands are rebuilt and memory is flushed.
To show this in practice, consider this command:
-class CmdTestID(Command):
+class CmdTestID(Command):
key = "testid"
- def func(self):
+ def func(self):
if not hasattr(self, "xval"):
self.xval = 0
@@ -527,9 +527,9 @@ the current execution of your command and wait for more before processing.
Create a command on the fly¶
This is also an advanced topic.
Commands can also be created and added to a cmdset on the fly. Creating a class instance with a keyword argument, will assign that keyword argument as a property on this paricular command:
-class MyCmdSet(CmdSet):
+class MyCmdSet(CmdSet):
- def at_cmdset_creation(self):
+ def at_cmdset_creation(self):
self.add(MyCommand(myvar=1, foo="test")
@@ -582,7 +582,7 @@ corresponds to a known command. This is how the command handler sequence looks f
Evennia does not use this return value at all by default. If you do, you must
thus do so asynchronously, using callbacks.
# in command class func()
- def callback(ret, caller):
+ def callback(ret, caller):
caller.msg(f"Returned is {ret}")
deferred = self.execute_command("longrunning")
deferred.addCallback(callback, self.caller)
diff --git a/docs/latest/Components/EvEditor.html b/docs/latest/Components/EvEditor.html
index 7172e4f310..e2295b62ca 100644
--- a/docs/latest/Components/EvEditor.html
+++ b/docs/latest/Components/EvEditor.html
@@ -132,7 +132,7 @@ search/replace, fill, dedent and more.
Launching the editor¶
The editor is created as follows:
-from evennia.utils.eveditor import EvEditor
+from evennia.utils.eveditor import EvEditor
EvEditor(caller,
loadfunc=None, savefunc=None, quitfunc=None,
@@ -156,10 +156,10 @@ It has no other mechanical function.
Working with EvEditor¶
This is an example command for setting a specific Attribute using the editor.
-from evennia import Command
-from evennia.utils import eveditor
+from evennia import Command
+from evennia.utils import eveditor
-class CmdSetTestAttr(Command):
+class CmdSetTestAttr(Command):
"""
Set the "test" Attribute using
the line editor.
@@ -169,15 +169,15 @@ It has no other mechanical function.
"""
key = "settestattr"
- def func(self):
+ def func(self):
"Set up the callbacks and launch the editor"
- def load(caller):
+ def load(caller):
"get the current value"
return caller.attributes.get("test")
- def save(caller, buffer):
+ def save(caller, buffer):
"save the buffer"
caller.attributes.add("test", buffer)
- def quit(caller):
+ def quit(caller):
"Since we define it, we must handle messages"
caller.msg("Editor exited")
key = f"{self.caller}/test"
@@ -193,22 +193,22 @@ It has no other mechanical function.
when reloading the game. In order to be persistent, an editor needs to have its callback functions
(loadfunc, savefunc and quitfunc) as top-level functions defined in the module. Since these
functions will be stored, Python will need to find them.
-from evennia import Command
-from evennia.utils import eveditor
+from evennia import Command
+from evennia.utils import eveditor
-def load(caller):
+def load(caller):
"get the current value"
return caller.attributes.get("test")
-def save(caller, buffer):
+def save(caller, buffer):
"save the buffer"
caller.attributes.add("test", buffer)
-def quit(caller):
+def quit(caller):
"Since we define it, we must handle messages"
caller.msg("Editor exited")
-class CmdSetTestAttr(Command):
+class CmdSetTestAttr(Command):
"""
Set the "test" Attribute using
the line editor.
@@ -218,7 +218,7 @@ functions will be stored, Python will need to find them.
"""
key = "settestattr"
- def func(self):
+ def func(self):
"Set up the callbacks and launch the editor"
key = f"{self.caller}/test"
# launch the editor
diff --git a/docs/latest/Components/EvMenu.html b/docs/latest/Components/EvMenu.html
index f0a464ee2a..05cb8dc378 100644
--- a/docs/latest/Components/EvMenu.html
+++ b/docs/latest/Components/EvMenu.html
@@ -178,14 +178,14 @@ chooses, they are forwarded to different nodes in the menu.
The EvMenu utility class is located in evennia/utils/evmenu.py.
It allows for easily adding interactive menus to the game; for example to implement Character creation, building commands or similar. Below is an example of offering NPC conversation choices:
This is how the example menu at the top of this page will look in code:
-from evennia.utils import evmenu
+from evennia.utils import evmenu
-def _handle_answer(caller, raw_input, **kwargs):
+def _handle_answer(caller, raw_input, **kwargs):
answer = kwargs.get("answer")
caller.msg(f"You chose {answer}!")
return "end" # name of next node
-def node_question(caller, raw_input, **kwargs):
+def node_question(caller, raw_input, **kwargs):
text = "Is your answer yes or no?"
options = (
{"key": ("[Y]es!", "yes", "y"),
@@ -200,7 +200,7 @@ It allows for easily adding interactive menus to the game; for example to implem
)
return text, options
-def node_end(caller, raw_input, **kwargs):
+def node_end(caller, raw_input, **kwargs):
text "Thanks for your answer. Goodbye!"
return text, None # empty options ends the menu
@@ -228,9 +228,9 @@ the menu (since it doesn’t return any options).
You can also write menus using the EvMenu templating language. This
allows you to use a text string to generate simpler menus with less boiler
plate. Let’s create exactly the same menu using the templating language:
-from evennia.utils import evmenu
+from evennia.utils import evmenu
-def _handle_answer(caller, raw_input, **kwargs):
+def _handle_answer(caller, raw_input, **kwargs):
answer = kwargs.get("answer")
caller.msg(f"You chose {answer}!")
return "end" # name of next node
@@ -274,7 +274,7 @@ uses the template-string and a mapping of callables (we must add
-def _skill_check(caller, raw_string, **kwargs):
+def _skill_check(caller, raw_string, **kwargs):
skills = kwargs.get("skills", [])
gold = kwargs.get("gold", 0)
@@ -284,7 +284,7 @@ uses the template-string and a mapping of callables (we must add
return next_node_name
-def node_guard(caller, raw_string, **kwarg):
+def node_guard(caller, raw_string, **kwarg):
text = (
'The guard looks at you suspiciously.\n'
'"No one is supposed to be in here ..."\n'
@@ -318,13 +318,13 @@ into combat!
Initializing the menu is done using a call to the evennia.utils.evmenu.EvMenu class. This is the most common way to do so - from inside a Command:
# in, for example gamedir/commands/command.py
-from evennia.utils.evmenu import EvMenu
+from evennia.utils.evmenu import EvMenu
-class CmdTestMenu(Command):
+class CmdTestMenu(Command):
key = "testcommand"
- def func(self):
+ def func(self):
EvMenu(self.caller, "world.mymenu")
@@ -376,15 +376,15 @@ menu. Temporary variables you store on a persistent
The Menu nodes¶
The EvMenu nodes consist of functions on one of these forms.
-def menunodename1(caller):
+def menunodename1(caller):
# code
return text, options
-def menunodename2(caller, raw_string):
+def menunodename2(caller, raw_string):
# code
return text, options
-def menunodename3(caller, raw_string, **kwargs):
+def menunodename3(caller, raw_string, **kwargs):
# code
return text, options
@@ -432,7 +432,7 @@ menu. Temporary variables you store on a persistent ¶
The options list describe all the choices available to the user when viewing this node. If options is returned as None, it means that this node is an Exit node - any text is displayed and then the menu immediately exits, running the exit_cmd if given.
Otherwise, options should be a list (or tuple) of dictionaries, one for each option. If only one option is available, a single dictionary can also be returned. This is how it could look:
-def node_test(caller, raw_string, **kwargs):
+def node_test(caller, raw_string, **kwargs):
text = "A goblin attacks you!"
@@ -473,7 +473,7 @@ ________________________________
Whether you want to use a key or rely on numbers is mostly a matter of style and the type of menu.
EvMenu accepts one important special key given only as "_default". This key is used when a user enters something that does not match any other fixed keys. It is particularly useful for getting user input:
-def node_readuser(caller, raw_string, **kwargs):
+def node_readuser(caller, raw_string, **kwargs):
text = "Please enter your name"
options = {"key": "_default",
@@ -495,15 +495,15 @@ ________________________________
option-key ‘goto’¶
This is the operational part of the option and fires only when the user chooses said option. Here are three ways to write it
-def _action_two(caller, raw_string, **kwargs):
+def _action_two(caller, raw_string, **kwargs):
# do things ...
return "calculated_node_to_go_to"
-def _action_three(caller, raw_string, **kwargs):
+def _action_three(caller, raw_string, **kwargs):
# do things ...
return "node_four", {"mode": 4}
-def node_select(caller, raw_string, **kwargs):
+def node_select(caller, raw_string, **kwargs):
text = ("select one",
"help - they all do different things ...")
@@ -539,11 +539,11 @@ ________________________________