From 57f411a6fae0f3334e8eb71a29cb476bbc414f39 Mon Sep 17 00:00:00 2001 From: Evennia docbuilder action Date: Sun, 20 Nov 2022 00:44:59 +0000 Subject: [PATCH] Updated HTML docs. --- docs/1.0-dev/.buildinfo | 2 +- docs/1.0-dev/.vale/write-good/README.html | 137 ------- .../Components/Batch-Command-Processor.html | 10 +- .../Bootstrap-Components-and-Utilities.html | 10 +- docs/1.0-dev/Components/Coding-Utils.html | 10 +- docs/1.0-dev/Components/Command-System.html | 10 +- .../Components/Components-Overview.html | 63 ++-- docs/1.0-dev/Components/Inputfuncs.html | 10 +- docs/1.0-dev/Components/Outputfuncs.html | 10 +- docs/1.0-dev/Components/Permissions.html | 10 +- .../1.0-dev/Components/Portal-And-Server.html | 30 +- docs/1.0-dev/Components/Server.html | 136 ------- docs/1.0-dev/Components/Web-API.html | 20 +- docs/1.0-dev/Components/Web-Admin.html | 20 +- docs/1.0-dev/Components/Webclient.html | 97 +++-- docs/1.0-dev/Components/Webserver.html | 20 +- docs/1.0-dev/Components/Website.html | 10 +- docs/1.0-dev/Concepts/Colors.html | 262 ++++++++----- docs/1.0-dev/Concepts/Soft-Code.html | 43 +-- .../Concepts/Using-MUX-as-a-Standard.html | 10 +- docs/1.0-dev/Contribs/Contrib-Buffs.html | 8 +- .../Contribs/Contrib-Character-Creator.html | 12 +- docs/1.0-dev/Contribs/Contrib-Dice.html | 8 +- docs/1.0-dev/Contribs/Contribs-Overview.html | 2 +- docs/1.0-dev/Contributing.html | 21 +- docs/1.0-dev/Evennia-Introduction.html | 85 +---- .../Beginner-Tutorial-Intro.html | 8 +- .../Beginner-Tutorial-Adding-Commands.html | 107 ++---- ...Beginner-Tutorial-Building-Quickstart.html | 2 +- ...ner-Tutorial-Evennia-Library-Overview.html | 72 ++-- .../Beginner-Tutorial-Gamedir-Overview.html | 48 +-- ...eginner-Tutorial-Learning-Typeclasses.html | 349 +++++++++--------- .../Part1/Beginner-Tutorial-Part1-Intro.html | 1 + ...er-Tutorial-Python-basic-introduction.html | 58 ++- ...r-Tutorial-Python-classes-and-objects.html | 99 ++--- .../Beginner-Tutorial-Tutorial-World.html | 3 +- docs/1.0-dev/Setup/Installation.html | 32 +- docs/1.0-dev/Setup/Settings-Default.html | 8 +- docs/1.0-dev/Setup/Settings.html | 12 +- docs/1.0-dev/Setup/Setup-Overview.html | 14 +- docs/1.0-dev/Setup/Start-Stop-Reload.html | 49 +-- .../_sources/.vale/write-good/README.md.txt | 27 -- .../Components/Components-Overview.md.txt | 39 +- .../Components/Portal-And-Server.md.txt | 10 +- .../1.0-dev/_sources/Components/Server.md.txt | 3 - .../_sources/Components/Webclient.md.txt | 51 +-- docs/1.0-dev/_sources/Concepts/Colors.md.txt | 153 ++++---- .../_sources/Concepts/Soft-Code.md.txt | 43 +-- .../Concepts/Using-MUX-as-a-Standard.md.txt | 10 +- .../Contribs/Contrib-Character-Creator.md.txt | 2 +- docs/1.0-dev/_sources/Contributing.md.txt | 21 +- .../_sources/Evennia-Introduction.md.txt | 81 +--- .../Beginner-Tutorial-Adding-Commands.md.txt | 105 ++---- ...ginner-Tutorial-Building-Quickstart.md.txt | 2 +- ...r-Tutorial-Evennia-Library-Overview.md.txt | 72 ++-- .../Beginner-Tutorial-Gamedir-Overview.md.txt | 48 +-- ...inner-Tutorial-Learning-Typeclasses.md.txt | 314 ++++++++-------- ...-Tutorial-Python-basic-introduction.md.txt | 60 ++- ...Tutorial-Python-classes-and-objects.md.txt | 104 +++--- .../Beginner-Tutorial-Tutorial-World.md.txt | 1 + .../_sources/Setup/Installation.md.txt | 33 +- docs/1.0-dev/_sources/Setup/Settings.md.txt | 2 +- .../_sources/Setup/Setup-Overview.md.txt | 4 +- .../_sources/Setup/Start-Stop-Reload.md.txt | 42 +-- .../_sources/api/evennia.contrib.rpg.md.txt | 1 + docs/1.0-dev/_sources/index.md.txt | 12 +- .../api/evennia.commands.default.account.html | 4 +- .../api/evennia.commands.default.admin.html | 4 +- ...evennia.commands.default.batchprocess.html | 4 +- .../evennia.commands.default.building.html | 16 +- .../api/evennia.commands.default.general.html | 20 +- .../api/evennia.commands.default.system.html | 4 +- .../api/evennia.commands.default.tests.html | 2 +- .../evennia.commands.default.unloggedin.html | 8 +- ....base_systems.email_login.email_login.html | 8 +- ...rib.full_systems.evscaperoom.commands.html | 28 +- ...ontrib.game_systems.clothing.clothing.html | 4 +- ...trib.game_systems.turnbattle.tb_basic.html | 4 +- ...trib.game_systems.turnbattle.tb_equip.html | 4 +- ...trib.game_systems.turnbattle.tb_items.html | 4 +- ...trib.game_systems.turnbattle.tb_magic.html | 4 +- ...trib.game_systems.turnbattle.tb_range.html | 4 +- ...trib.grid.extended_room.extended_room.html | 4 +- .../api/evennia.contrib.rpg.dice.dice.html | 4 +- ...ontrib.tutorials.evadventure.commands.html | 8 +- ...ntrib.tutorials.red_button.red_button.html | 16 +- ...trib.tutorials.tutorial_world.objects.html | 16 +- ...ontrib.tutorials.tutorial_world.rooms.html | 12 +- ...utils.git_integration.git_integration.html | 4 +- docs/1.0-dev/api/evennia.utils.eveditor.html | 4 +- docs/1.0-dev/api/evennia.utils.evmenu.html | 4 +- docs/1.0-dev/api/evennia.utils.evmore.html | 4 +- docs/1.0-dev/index.html | 47 +-- docs/1.0-dev/objects.inv | Bin 157808 -> 157712 bytes docs/1.0-dev/searchindex.js | 2 +- 95 files changed, 1370 insertions(+), 2035 deletions(-) delete mode 100644 docs/1.0-dev/.vale/write-good/README.html delete mode 100644 docs/1.0-dev/Components/Server.html delete mode 100644 docs/1.0-dev/_sources/.vale/write-good/README.md.txt delete mode 100644 docs/1.0-dev/_sources/Components/Server.md.txt diff --git a/docs/1.0-dev/.buildinfo b/docs/1.0-dev/.buildinfo index 262d6c66d7..a808e3f59e 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: 2a039604581b49aee649bfc0adbfc647 +config: c0024f80050e9e2b9dfd653b5cfcd067 tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs/1.0-dev/.vale/write-good/README.html b/docs/1.0-dev/.vale/write-good/README.html deleted file mode 100644 index 447c3f5b77..0000000000 --- a/docs/1.0-dev/.vale/write-good/README.html +++ /dev/null @@ -1,137 +0,0 @@ - - - - - - - - - <no title> — Evennia 1.0-dev documentation - - - - - - - - - - - - - -
- -
- -
-
- -

Based on write-good.

-
-

Naive linter for English prose for developers who can’t write good and wanna learn to do other stuff good too.

-
-
The MIT License (MIT)
-
-Copyright (c) 2014 Brian Ford
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-
- - -
-
-
- -
- - - - \ No newline at end of file diff --git a/docs/1.0-dev/Components/Batch-Command-Processor.html b/docs/1.0-dev/Components/Batch-Command-Processor.html index 212c6b1d95..df9beb9447 100644 --- a/docs/1.0-dev/Components/Batch-Command-Processor.html +++ b/docs/1.0-dev/Components/Batch-Command-Processor.html @@ -17,7 +17,7 @@ - + -

Remember, plugins are load-order dependent, so make sure the new <script> tag comes before the -goldenlayout.js

+

Remember, plugins are load-order dependent, so make sure the new <script> tag comes before the goldenlayout.js.

Next, create a new plugin file mygame/web/static/webclient/js/plugins/myplugin.js and edit it.

let myplugin = (function () {
@@ -405,9 +391,10 @@ edit it.

window.plugin_handler.add("myplugin", myplugin);
-

You can then add “mycomponent” to an item’s componentName in your goldenlayout_default_config.js.

+

You can then add “mycomponent” to an item’s componentName in your goldenlayout_default_config.js.

Make sure to stop your server, evennia collectstatic, and restart your server. Then make sure to clear your browser cache before loading the webclient page.

+ @@ -426,10 +413,10 @@ window.plugin_handler.add("myplugin", myplugin); modules |
  • - next |
  • - previous |
  • diff --git a/docs/1.0-dev/Components/Webserver.html b/docs/1.0-dev/Components/Webserver.html index 58c5e876ef..9c9226d68b 100644 --- a/docs/1.0-dev/Components/Webserver.html +++ b/docs/1.0-dev/Components/Webserver.html @@ -17,8 +17,8 @@ - - + +

    Ignoring the docstrings (which you can read if you want), this is the only really active code in the module.

    -

    We can see that we import Command from evennia and use the from ... import ... as ... form to rename it -to BaseCommand. This is so we can let our child class also be named Command for reference. The class -itself doesn’t do anything, it just has pass. So in the same way as Object in the previous lesson, this -class is identical to its parent.

    +

    We can see that we import Command from evennia and use the from ... import ... as ... form to rename it to BaseCommand. This is so we can let our child class also be named Command to make it easier to reference. The class itself doesn’t do anything, it just has pass. So in the same way as Object and Character in the previous lessons, this class is identical to its parent.

    -

    The commented out default_cmds gives us access to Evennia’s default commands for easy overriding. We’ll try -that a little later.

    +

    The commented out default_cmds gives us access to Evennia’s default commands for easy overriding. We’ll try that a little later.

    -

    We could modify this module directly, but to train imports we’ll work in a separate module. Open a new file -mygame/commands/mycommands.py and add the following code:

    -
    
    +

    We could modify this module directly, but let’s work in a separate module just for the heck of it. Open a new file mygame/commands/mycommands.py and add the following code:

    +
    # in mygame/commands/mycommands.py
    +
     from commands.command import Command
     
     class CmdEcho(Command):
    @@ -194,15 +180,12 @@ what you will use to call this command later.

    -

    Our EchoCmdSet class must have an at_cmdset_creation method, named exactly -like this - this is what Evennia will be looking for when setting up the cmdset later, so -if you didn’t set it up, it will use the parent’s version, which is empty. Inside we add the -command class to the cmdset by self.add(). If you wanted to add more commands to this CmdSet you -could just add more lines of self.add after this.

    +

    Our EchoCmdSet class must have an at_cmdset_creation method, named exactly like this - this is what Evennia will be looking for when setting up the cmdset later, so if you didn’t set it up, it will use the parent’s version, which is empty. Inside we add the command class to the cmdset by self.add(). If you wanted to add more commands to this CmdSet you could just add more lines of self.add after this.

    Finally, let’s add this command to ourselves so we can try it out. In-game you can experiment with py again:

    -
    > py self.cmdset.add("commands.mycommands.MyCmdSet")
    +
    > py me.cmdset.add("commands.mycommands.MyCmdSet")
     
    +

    The me.cmdset is the store of all cmdsets stored on us. By giving the path to our CmdSet class, it will be added.

    Now try

    > echo
     Command echo has no defined `func()` - showing on-command variables:
    @@ -210,9 +193,7 @@ Command echo has no defined `func()` - showing on-command variables:
     ...
     
    -

    You should be getting a long list of outputs. The reason for this is that your echo function is not really -“doing” anything yet and the default function is then to show all useful resources available to you when you -use your Command. Let’s look at some of those listed:

    +

    echo works! You should be getting a long list of outputs. The reason for this is that your echo function is not really “doing” anything yet and the default function is then to show all useful resources available to you when you use your Command. Let’s look at some of those listed:

    Command echo has no defined `func()` - showing on-command variables:
     obj (<class 'typeclasses.characters.Character'>): YourName
     lockhandler (<class 'evennia.locks.lockhandler.LockHandler'>): cmd:all()
    @@ -244,17 +225,13 @@ command string given (self.cmdstring): echo
     current cmdset (self.cmdset): ChannelCmdSet
     
    -

    These are all properties you can access with . on the Command instance, such as .key, .args and so on. -Evennia makes these available to you and they will be different every time a command is run. The most -important ones we will make use of now are:

    +

    These are all properties you can access with . on the Command instance, such as .key, .args and so on. Evennia makes these available to you and they will be different every time a command is run. The most important ones we will make use of now are:

    • caller - this is ‘you’, the person calling the command.

    • -
    • args - this is all arguments to the command. Now it’s empty, but if you tried echo foo bar you’d find -that this would be " foo bar".

    • +
    • args - this is all arguments to the command. Now it’s empty, but if you tried echo foo bar you’d find that this would be " foo bar".

    • obj - this is object on which this Command (and CmdSet) “sits”. So you, in this case.

    -

    The reason our command doesn’t do anything yet is because it’s missing a func method. This is what Evennia -looks for to figure out what a Command actually does. Modify your CmdEcho class:

    +

    The reason our command doesn’t do anything yet is because it’s missing a func method. This is what Evennia looks for to figure out what a Command actually does. Modify your CmdEcho class:

    # ...
     
     class CmdEcho(Command):
    @@ -273,14 +250,13 @@ looks for to figure out what a Command actually does. Modify your # ...
     
    -

    First we added a docstring. This is always a good thing to do in general, but for a Command class, it will also -automatically become the in-game help entry! Next we add the func method. It has one active line where it -makes use of some of those variables we found the Command offers to us. If you did the -basic Python tutorial, you will recognize .msg - this will send a message -to the object it is attached to us - in this case self.caller, that is, us. We grab self.args and includes -that in the message.

    -

    Since we haven’t changed MyCmdSet, that will work as before. Reload and re-add this command to ourselves to -try out the new version:

    +

    First we added a docstring. This is always a good thing to do in general, but for a Command class, it will also automatically become the in-game help entry!

    + +

    Next we add the func method. It has one active line where it makes use of some of those variables the Command class offers to us. If you did the basic Python tutorial, you will recognize .msg - this will send a message to the object it is attached to us - in this case self.caller, that is, us. We grab self.args and includes that in the message.

    +

    Since we haven’t changed MyCmdSet, that will work as before. Reload and re-add this command to ourselves to try out the new version:

    > reload
     > py self.cmdset.add("commands.mycommands.MyCmdSet")
     > echo
    @@ -292,14 +268,12 @@ Echo: ''
     Echo: ' Woo Tang!'
     
    -

    Note that there is an extra space before Woo!. That is because self.args contains the everything after -the command name, including spaces. Evennia will happily understand if you skip that space too:

    +

    Note that there is an extra space before Woo!. That is because self.args contains everything after the command name, including spaces. Evennia will happily understand if you skip that space too:

    > echoWoo Tang!
     Echo: 'Woo Tang!'
     
    -

    There are ways to force Evennia to require an initial space, but right now we want to just ignore it since -it looks a bit weird for our echo example. Tweak the code:

    +

    There are ways to force Evennia to require an initial space, but right now we want to just ignore it since it looks a bit weird for our echo example. Tweak the code:

    # ...
     
     class CmdEcho(Command):
    @@ -318,9 +292,7 @@ it looks a bit weird for our echo example. Tweak the code:

    # ...
    -

    The only difference is that we called .strip() on self.args. This is a helper method available on all -strings - it strips out all whitespace before and after the string. Now the Command-argument will no longer -have any space in front of it.

    +

    The only difference is that we called .strip() on self.args. This is a helper method available on all strings - it strips out all whitespace before and after the string. Now the Command-argument will no longer have any space in front of it.

    > reload
     > py self.cmdset.add("commands.mycommands.MyCmdSet")
     > echo Woo Tang!
    @@ -331,7 +303,7 @@ Echo: 'Woo Tang!'
     
    > help echo
     
    -

    You will get the docstring you put in your Command-class.

    +

    You will get the docstring you put in your Command-class!

    8.1.1. Making our cmdset persistent

    It’s getting a little annoying to have to re-add our cmdset every time we reload, right? It’s simple @@ -340,7 +312,7 @@ enough to make echo

    Now you can reload as much as you want and your code changes will be available directly without -needing to re-add the MyCmdSet again. To remove the cmdset again, do

    +needing to re-add the MyCmdSet again. To remove the cmdset again, you’d do

    > py self.cmdset.remove("commands.mycommands.MyCmdSet")
     
    @@ -354,7 +326,7 @@ someone in the face! This is how we want it to work:

    You hit <target> with full force!
    -

    Not only that, we want the to see

    +

    Not only that, we want the <target> to see

    You got hit by <hitter> with full force!
     
    @@ -432,11 +404,9 @@ else: the else condition is given, it will run if none of the other conditions was truthy. In Python the if..elif..else structure also serves the same function as case in some other languages.

    -
      -
    • Line 15 has our first conditional, an if statement. This is written on the form if <condition>: and only -if that condition is ‘truthy’ will the indented code block under the if statement run. To learn what is truthy in -Python it’s usually easier to learn what is “falsy”:

        +
      • Line 15 has our first conditional, an if statement. This is written on the form if <condition>: and only if that condition is ‘truthy’ will the indented code block under the if statement run. To learn what is truthy in Python it’s usually easier to learn what is “falsy”:

        +
        • False - this is a reserved boolean word in Python. The opposite is True.

        • None - another reserved word. This represents nothing, a null-result or value.

        • 0 or 0.0

        • @@ -444,14 +414,12 @@ Python it’s usually easier to learn what is “falsy”:

        • Empty iterables we haven’t seen yet, like empty lists [], empty tuples () and empty dicts {}.

        • Everything else is “truthy”.

        -

        Line 16’s condition is not args. The not inverses the result, so if args is the empty string (falsy), the -whole conditional becomes truthy. Let’s continue in the code:

      • +
      • Line 16’s condition is not args. The not inverses the result, so if args is the empty string (falsy), the whole conditional becomes truthy. Let’s continue in the code:

      • Lines 16-17: This code will only run if the if statement is truthy, in this case if args is the empty string.

      • Line 17: return is a reserved Python word that exits func immediately.

      • Line 18: We use self.caller.search to look for the target in the current location.

      • -
      • Lines 19-20: A feature of .search is that it will already inform self.caller if it couldn’t find the target. -In that case, target will be None and we should just directly return.

      • +
      • Lines 19-20: A feature of .search is that it will already inform self.caller if it couldn’t find the target. In that case, target will be None and we should just directly return.

      • Lines 21-22: At this point we have a suitable target and can send our punching strings to each.

      Finally we must also add this to a CmdSet. Let’s add it to MyCmdSet which we made persistent earlier.

      @@ -470,9 +438,7 @@ In that case, targe

      With longer code snippets to try, it gets more and more likely you’ll make an error and get a traceback when you reload. This will either appear directly in-game or in your log (view it with evennia -l in a terminal). -Don’t panic; tracebacks are your friends - they are to be read bottom-up and usually describe -exactly where your problem is. Refer to The Python intro <Python-basic-introduction.html>_ for -more hints. If you get stuck, reach out to the Evennia community for help.

      +Don’t panic; tracebacks are your friends - they are to be read bottom-up and usually describe exactly where your problem is. Refer to The Python introduction lesson for more hints. If you get stuck, reach out to the Evennia community for help.

      Next we reload to let Evennia know of these code changes and try it out:

      > reload
      @@ -494,8 +460,7 @@ You hit Smaug with full force!
       
       

      8.2. Summary

      -

      In this lesson we learned how to create our own Command, add it to a CmdSet and then to ourselves. -We also upset a dragon.

      +

      In this lesson we learned how to create our own Command, add it to a CmdSet and then to ourselves. We also upset a dragon.

      In the next lesson we’ll learn how to hit Smaug with different weapons. We’ll also get into how we replace and extend Evennia’s default Commands.

      diff --git a/docs/1.0-dev/Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Building-Quickstart.html b/docs/1.0-dev/Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Building-Quickstart.html index a3c627dc12..f384f2a72a 100644 --- a/docs/1.0-dev/Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Building-Quickstart.html +++ b/docs/1.0-dev/Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Building-Quickstart.html @@ -119,7 +119,7 @@

      1. Using commands and building stuff

      In this lesson we will test out what we can do in-game out-of-the-box. Evennia ships with around 90 default commands, and while you can override those as you please, -they can be quite useful.

      +the defaults can be quite useful.

      Connect and log into your new game and you will end up in the “Limbo” location. This is the only room in the game at this point. Let’s explore the commands a little.

      The default commands has syntax similar to MUX:

      diff --git a/docs/1.0-dev/Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Evennia-Library-Overview.html b/docs/1.0-dev/Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Evennia-Library-Overview.html index 3de0b8b749..492d96d849 100644 --- a/docs/1.0-dev/Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Evennia-Library-Overview.html +++ b/docs/1.0-dev/Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Evennia-Library-Overview.html @@ -67,6 +67,7 @@
    • 6. Overview of the Evennia library
    @@ -113,16 +114,13 @@

    API stands for Application Programming Interface, a description for how to access the resources of a program or library.

    -

    A good place to start exploring Evennia is the Evenia-API frontpage. -This page sums up the main components of Evennia with a short description of each. Try clicking through -to a few entries - once you get deep enough you’ll see full descriptions -of each component along with their documentation. You can also click [source] to see the full Python source -for each thing.

    -

    You can also browse the evennia repository on github. This is exactly -what you can download from us. The github repo is also searchable.

    -

    Finally, you can clone the evennia repo to your own computer and read the sources locally. This is necessary -if you want to help with Evennia’s development itself. See the -extended install instructions if you want to do this.

    +

    There are several good ways to explore the Evennia library.

    +
      +
    • This documentation contains the Evennia-API docs, generated automatically from sources. Try clicking through to a few entries - once you get deep enough you’ll see full descriptions of each component along with their documentation. You can also click [source] to see the full Python source code for each thing.

    • +
    • There are separate doc pages for each component if you want more detailed explanations.

    • +
    • You can browse the evennia repository on github. This is exactly what you can download from us.

    • +
    • Finally, you can clone the evennia repo to your own computer and read the sources. This is necessary if you want to really understand what’s going on, or help with Evennia’s development. See the extended install instructions if you want to do this.

    • +

    6.1. Where is it?

    If Evennia is installed, you can import from it simply with

    @@ -132,9 +130,8 @@ from evennia.some_module.other_module import SomeClass

    and so on.

    -

    If you installed Evennia with pip install, the library folder will be installed deep inside your Python -installation. If you cloned the repo there will be a folder evennia on your hard drive there.

    -

    If you cloned the repo or read the code on github you’ll find this being the outermost structure:

    +

    If you installed Evennia with pip install, the library folder will be installed deep inside your Python installation; you are better off looking at it on github. If you cloned it, you should have an evennia folder to look into.

    +

    You’ll find this being the outermost structure:

    evennia/
         bin/
         CHANGELOG.md
    @@ -150,7 +147,7 @@ the actual library, the thing covered by the API auto-docs and what you
     

    The evennia/docs/ folder contains the sources for this documentation. See contributing to the docs if you want to learn more about how this works.

    -

    This the the structure of the Evennia library:

    +

    This is the structure of the Evennia library:

    • evennia

        @@ -187,21 +184,29 @@ from here to mygame

        The __init__.py file is a special Python filename used to represent a Python ‘package’. When you import evennia on its own, you import this file. When you do evennia.foo Python will first look for a property .foo in __init__.py and then for a module or folder of that name in the same location.

        -

        While all the actual Evennia code is found in the various folders, the __init__.py represents the entire -package evennia. It contains “shortcuts” to code that is actually located elsewhere. Most of these shortcuts -are listed if you scroll down a bit on the Evennia-API page.

        +

        While all the actual Evennia code is found in the various folders, the __init__.py represents the entire package evennia. It contains “shortcuts” to code that is actually located elsewhere. Most of these shortcuts are listed if you scroll down a bit on the Evennia-API page.

        6.2. An example of exploring the library

        -

        In the previous lesson we took a brief look at mygame/typeclasses/objects as an example of a Python module. Let’s -open it again. Inside is the Object class, which inherits from DefaultObject. -Near the top of the module is this line:

        +

        In the previous lesson we took a brief look at mygame/typeclasses/objects as an example of a Python module. Let’s open it again.

        +
        """
        +module docstring
        +"""
        +from evennia import DefaultObject
        +
        +class Object(DefaultObject):
        +    """
        +    class docstring
        +    """
        +    pass
        +
        +
        +

        We have the Object class, which inherits from DefaultObject. Near the top of the module is this line:

        from evennia import DefaultObject
         
        -

        We want to figure out just what this DefaultObject offers. Since this is imported directly from evennia, we -are actually importing from evennia/__init__.py.

        -

        Look at Line 159 of evennia/__init__.py and you’ll find this line:

        +

        We want to figure out just what this DefaultObject offers. Since this is imported directly from evennia, we are actually importing from evennia/__init__.py.

        +

        Look at Line 160 of evennia/__init__.py and you’ll find this line:

        from .objects.objects import DefaultObject
         
        @@ -210,21 +215,22 @@ are actually importing from The first full-stop in from .objects.objects ... means that we are importing from the current location. This is called a relative import. By comparison, from evennia.objects.objects is an absolute import. In this particular case, the two would give the same result.

        -

        You can also look at the right section of the API frontpage and click through -to the code that way.

        +

        You can also look at the right section of the API frontpage and click through to the code that way.

        -

        The fact that DefaultObject is imported into __init__.py here is what makes it possible to also import -it as from evennia import DefaultObject even though the code for the class is not actually here.

        -

        So to find the code for DefaultObject we need to look in evennia/objects/objects.py. Here’s how -to look it up in the docs:

        +

        The fact that DefaultObject is imported into __init__.py here is what makes it possible to also import it as from evennia import DefaultObject even though the code for the class is not actually here.

        +

        So to find the code for DefaultObject we need to look in evennia/objects/objects.py. Here’s how to look it up in the docs:

        1. Open the API frontpage

        2. -
        3. Locate the link to evennia.objects.objects and click on it. -3 You are now in the python module. Scroll down (or search in your web browser) to find the DefaultObject class. -4 You can now read what this does and what methods are on it. If you want to see the full source, click the -[source] link next to it.

        4. +
        5. Locate the link to evennia.objects.objects and click on it.

        6. +
        7. You are now in the python module. Scroll down (or search in your web browser) to find the DefaultObject class.

        8. +
        9. You can now read what this does and what methods are on it. If you want to see the full source, click the [source] link next to it.

        +
        +

        6.3. Conclusions

        +

        This is an important lesson. It teaches you how to find information for yourself. Knowing how to follow the class inheritance tree and navigate to things you need is a big part in learning a new library like Evennia.

        +

        Next we’ll start to make use of what we have learned so far and combine it with the building blocks provided by Evennia.

        +
        diff --git a/docs/1.0-dev/Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Gamedir-Overview.html b/docs/1.0-dev/Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Gamedir-Overview.html index 3d8bbcc00b..4bf0cbce7e 100644 --- a/docs/1.0-dev/Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Gamedir-Overview.html +++ b/docs/1.0-dev/Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Gamedir-Overview.html @@ -116,30 +116,24 @@

        4. Overview of your new Game Dir

        -

        Next we will take a little detour to look at the Tutorial World. This is a little solo adventure -that comes with Evennia, a showcase for some of the things that are possible.

        -

        Now we have ‘run the game’ a bit and started with our forays into Python from inside Evennia. -It is time to start to look at how things look ‘outside of the game’. Let’s do a tour of your game-dir -Like everywhere in the docs we’ll assume it’s called mygame.

        +

        Until now we have ‘run the game’ a bit and started playing with Python inside Evennia. +It is time to start to look at how things look ‘outside of the game’.

        +

        Let’s do a tour of your game-dir (we assume it’s called mygame).

        When looking through files, ignore files ending with .pyc and the __pycache__ folder if it exists. This is internal Python compilation files that you should never need to touch. Files __init__.py is also often empty and can be ignored (they have to do with Python package management).

        -

        You may have noticed when we were building things in-game that we would often refer to code through -“python paths”, such as

        +

        You may have noticed when we were building things in-game that we would often refer to code through “python paths”, such as

        +
        create/drop button:tutorial_examples.red_button.RedButton
        +
        +
        +

        This is a fundamental aspect of coding Evennia - you create code and then you tell Evennia where that code is and when it should be used. Above we told it to create a red button by pulling from specific code in the contrib/ folder. The same principle is true everywhere. So it’s important to know where code is and how you point to it correctly.

        -
        create/drop button:tutorial_examples.red_button.RedButton
        -
        -
        -

        This is a fundamental aspect of coding Evennia - you create code and then you tell Evennia where that -code is and when it should be used. Above we told it to create a red button by pulling from specific code -in the contribs/ folder but the same principle is true everywhere. So it’s important to know where code is -and how you point to it correctly.

        • mygame/

            @@ -163,11 +157,8 @@ building, such as build scripts and rules modules that don’t fit with one of t
          -

          The server/ subfolder should remain the way it is - Evennia expects this. But you could in -principle change the structure of the rest of your game dir as best fits your preference. -Maybe you don’t need a world/ folder but prefer many folders with different aspects of your world? -Or a new folder ‘rules’ for your RPG rules? This is fine. If you move things around you just need -to update Evennia’s default settings to point to the right places in the new structure.

          +

          The server/ subfolder should remain the way it is - Evennia expects this. But you can change the structure of the rest of your game dir as best fits your preferences. +Maybe you don’t want a single world/ folder but prefer many folders with different aspects of your world? A new folder ‘rules’ for your RPG rules? Group your commands with your objects instead of having them separate? This is fine. If you move things around you just need to update Evennia’s default settings to point to the right places in the new structure.

          4.1. commands/

          @@ -211,9 +202,8 @@ means that they must be extended with valid Python. You can also add logic to th knows where they are and will read them to configure itself at startup.

          • settings.py - this is by far the most important file. It’s nearly empty by default, rather you -are expected to copy&paste the changes you need from evennia/default_settings.py. -The default settings file is extensively documented. Importing/accessing the values in the settings -file is done in a special way, like this:

            +are expected to copy&paste the changes you need from evennia/default_settings.py. +The default settings file is extensively documented. Importing/accessing the values in the settings file is done in a special way, like this:

              from django.conf import settings 
             
            @@ -221,8 +211,7 @@ file is done in a special way, like this:

              telnet_port = settings.TELNET_PORT
             
            -

            You cannot assign to the settings file dynamically; you must change the settings.py file directly to -change a setting.

            +

            You cannot assign to the settings file dynamically; you must change the settings.py file directly to change a setting. See Settings documentation for more details.

          • secret_settings.py - If you are making your code effort public, you may not want to share all settings online. There may be server-specific secrets or just fine-tuning for your game systems that you prefer be kept secret @@ -284,14 +273,12 @@ an entire planet or an actual dungeon room.

          • Exits is another subclass of Object. Exits link one Room to another.

          • scripts.py (Python-path: typeclasses.scripts) - Scripts are ‘out-of-character’ objects. They have no location in-game and can serve as basis for -anything that needs database persistence, such as combat, weather, or economic systems. They also -have the ability to execute code repeatedly, on a timer.

          • +anything that needs database persistence, such as combat, weather, or economic systems. They also have the ability to execute code repeatedly, on a timer.

          4.2.4. web/

          -

          This folder contains folders for overriding the default web-presence of Evennia with your own designs. -Most of these folders are empty except for a README file or a subset of other empty folders.

          +

          This folder contains folders for overriding the default web-presence of Evennia with your own designs. Most of these folders are empty except for a README file or a subset of other empty folders. See the Web overview for more details (we’ll also get back to the web later in this beginner tutorial).

          • media/ - this empty folder is where you can place your own images or other media files you want the web server to serve. If you are releasing your game with a lot of media (especially if you want videos) you @@ -316,10 +303,7 @@ people change and re-structure this in various ways to better fit their ideas.

            batch_cmds.ev - This is an .ev file, which is essentially just a list of Evennia commands to execute in sequence. This one is empty and ready to expand on. The Tutorial World was built with such a batch-file.

          • -
          • prototypes.py - A prototype is a way -to easily vary objects without changing their base typeclass. For example, one could use prototypes to -tell that Two goblins, while both of the class ‘Goblin’ (so they follow the same code logic), should have different -equipment, stats and looks.

          • +
          • prototypes.py - A prototype is a way to easily vary objects without changing their base typeclass. For example, one could use prototypes to tell that Two goblins, while both of the class ‘Goblin’ (so they follow the same code logic), should have different equipment, stats and looks.

        diff --git a/docs/1.0-dev/Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Learning-Typeclasses.html b/docs/1.0-dev/Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Learning-Typeclasses.html index 1bfc8cc137..1858ab2b0a 100644 --- a/docs/1.0-dev/Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Learning-Typeclasses.html +++ b/docs/1.0-dev/Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Learning-Typeclasses.html @@ -72,7 +72,8 @@
    • 7.2. Typeclasses
    • 7.3. Modifying ourselves
        @@ -170,25 +171,23 @@ open it:

        """ from evennia import DefaultObject -class Object(DefaultObject): +class ObjectParent: + """ + class docstring + """ + pass + +class Object(ObjectParent, DefaultObject): """ class docstring """ pass
    -

    So we have a class Object that inherits from DefaultObject, which we have imported from Evennia. -The class itself doesn’t do anything (it just passes) but that doesn’t mean it’s useless. As we’ve seen, -it inherits all the functionality of its parent. It’s in fact an exact replica of DefaultObject right now. -If we knew what kind of methods and resources were available on DefaultObject we could add our own and -change the way it works!

    -
    -

    Hint: We will get back to this, but to learn what resources an Evennia parent like DefaultObject offers, -easiest is to peek at its API documentation. The docstring for -the Object class can also help.

    -
    -

    One thing that Evennia classes offers and which you don’t get with vanilla Python classes is persistence. As -you’ve found, Fluffy, Cuddly and Smaug are gone once we reload the server. Let’s see if we can fix this.

    +

    So we have a class Object that inherits from ObjectParent (which is empty) and DefaultObject, which we have imported from Evennia. The ObjectParent acts as a place to put code you want all +of your Objects to have. We’ll focus on Object and DefaultObject for now.

    +

    The class itself doesn’t do anything (it just passes) but that doesn’t mean it’s useless. As we’ve seen, it inherits all the functionality of its parent. It’s in fact an exact replica of DefaultObject right now. Once we know what kind of methods and resources are available on DefaultObject we could add our own and change the way it works!

    +

    One thing that Evennia classes offers and which you don’t get with vanilla Python classes is persistence - they survive a server reload since they are stored in the database.

    Go back to mygame/typeclasses/monsters.py. Change it as follows:

    
     from typeclasses.objects import Object
    @@ -218,15 +217,13 @@ you’ve found, Fluffy, Cuddly and Smaug are gone once we reload the server. Let
     
     
    -

    Don’t forget to save. We removed Monster.__init__ and made Monster inherit from Evennia’s Object (which in turn -inherits from Evennia’s DefaultObject, as we saw). By extension, this means that Dragon also inherits -from DefaultObject, just from further away!

    +

    Don’t forget to save. We removed Monster.__init__ and made Monster inherit from Evennia’s Object (which in turn inherits from Evennia’s DefaultObject, as we saw). By extension, this means that Dragon also inherits from DefaultObject, just from further away!

    7.1.1. Making a new object by calling the class

    First reload the server as usual. We will need to create the dragon a little differently this time:

    > py
     > from typeclasses.monsters import Dragon
    @@ -239,6 +236,10 @@ The world trembles.
     

    Smaug works the same as before, but we created him differently: first we used Dragon(db_key="Smaug", db_location=here) to create the object, and then we used smaug.save() afterwards.

    +
    > quit()
     Python Console is closing.
     > look 
    @@ -249,9 +250,7 @@ Python Console is closing.
     > look 
     
    -

    He’s still there… What we just did was to create a new entry in the database for Smaug. We gave the object -its name (key) and set its location to our current location (remember that here is just something available -in the py command, you can’t use it elsewhere).

    +

    He’s still there… What we just did was to create a new entry in the database for Smaug. We gave the object its name (key) and set its location to our current location.

    To make use of Smaug in code we must first find him in the database. For an object in the current location we can easily do this in py by using me.search():

    > py smaug = me.search("Smaug") ; smaug.firebreath()
    @@ -264,83 +263,103 @@ Smaug breathes fire!
     

    Creating Smaug like we did above is nice because it’s similar to how we created non-database bound Python instances before. But you need to use db_key instead of key and you also have to remember to call .save() afterwards. Evennia has a helper function that is more common to use, -called create_object:

    -
    > py fluffy = evennia.create_object('typeclases.monster.Monster', key="Fluffy", location=here)
    +called create_object. Let’s recreate Cuddly this time:

    +
    > py evennia.create_object('typeclasses.monster.Monster', key="Cuddly", location=here)
     > look 
     
    -

    Boom, Fluffy should now be in the room with you, a little less scary than Smaug. You specify the -python-path to the code you want and then set the key and location. Evennia sets things up and saves for you.

    -

    If you want to find Fluffy from anywhere, you can use Evennia’s search_object helper:

    -
    > fluffy = evennia.search_object("Fluffy")[0] ; fluffy.move_around()
    -Fluffy is moving! 
    +

    Boom, Cuddly should now be in the room with you, a little less scary than Smaug. You specify the +python-path to the code you want and then set the key and location (if you had the Monster class already imported, you could have passed that too). Evennia sets things up and saves for you.

    +

    If you want to find Smaug from anywhere (not just in the same room), you can use Evennia’s search_object function:

    +
    > cuddly = evennia.search_object("Cuddly")[0] ; cuddly.move_around()
    +Cuddly is moving!
     
    -

    The [0] is because search_object always returns a list of zero, one or more found objects. The [0] -means that we want the first element of this list (counting in Python always starts from 0). If there were -multiple Fluffies we could get the second one with [1].

    +

    The [0] is because search_object always returns a list of zero, one or more found objects. The [0] means that we want the first element of this list (counting in Python always starts from 0). If there were multiple Cuddlies we could get the second one with [1].

    7.1.3. Creating using create-command

    -

    Finally, you can also create a new Dragon using the familiar builder-commands we explored a few lessons ago:

    -
    > create/drop Cuddly:typeclasses.monsters.Monster
    +

    Finally, you can also create a new dragon using the familiar builder-commands we explored a few lessons ago:

    +
    > create/drop Fluffy:typeclasses.monsters.Dragon
     
    -

    Cuddly is now in the room. After learning about how objects are created you’ll realize that all this command really -does is to parse your input, figure out that /drop means to “give the object the same location as the caller”, -and then do a call akin to

    -
    evennia.create_object("typeclasses.monsters.Monster", key="Cuddly", location=here)
    +

    Fluffy is now in the room. After learning about how objects are created you’ll realize that all this command really does is to parse your input, figure out that /drop means to “give the object the same location as the caller”, and then do a call very similar to

    +
    evennia.create_object("typeclasses.monsters.Dragon", key="Cuddly", location=here)
     
    -

    That’s pretty much all there is to the mighty create command! The rest is just parsing for the command -to understand just what the user wants to create.

    +

    That’s pretty much all there is to the mighty create command! The rest is just parsing for the command to understand just what the user wants to create.

    7.2. Typeclasses

    -

    The Object (and DefafultObject class we inherited from above is what we refer to as a Typeclass. This -is an Evennia thing. The instance of a typeclass saves itself to the database when it is created, and after -that you can just search for it to get it back. We use the term typeclass or typeclassed to differentiate -these types of classes and objects from the normal Python classes, whose instances go away on a reload.

    +

    The Object (and DefafultObject class we inherited from above is what we refer to as a Typeclass. This is an Evennia thing. The instance of a typeclass saves itself to the database when it is created, and after that you can just search for it to get it back.

    +

    We use the term typeclass or typeclassed to differentiate these types of classes and objects from the normal Python classes, whose instances go away on a reload.

    The number of typeclasses in Evennia are so few they can be learned by heart:

    -
      -
    • evennia.DefaultObject: This is the parent of all in-game entities - everything with a location. Evennia makes -a few very useful child classes of this class:

      -
        -
      • evennia.DefaultCharacter: The default entity represening a player avatar in-game.

      • -
      • evennia.DefaultRoom: A location in the game world.

      • -
      • evennia.DefaultExit: A link between locations.

      • -
      -
    • -
    • evennia.DefaultAccount: The OOC representation of a player, holds password and account info.

    • -
    • evennia.DefaultChannel: In-game channels. These could be used for all sorts of in-game communication.

    • -
    • evennia.DefaultScript: Out-of-game objects, with no presence in the game world. Anything you want to create that -needs to be persistent can be stored with these entities, such as combat state, economic systems or what have you.

    • -
    -

    If you take a look in mygame/typeclasses/ you’ll find modules for each of these. Each contains an empty child -class ready that already inherits from the right parent, ready for you to modify or build from:

    -
      -
    • mygame/typeclasses/objects.py has class Object(DefaultObject), a class directly inheriting the basic in-game entity, this -works as a base for any object.

    • -
    • mygame/typeclasses/characters.py has class Character(DefaultCharacter)

    • -
    • mygame/typeclasses/rooms.py has class Room(DefaultRoom)

    • -
    • mygame/typeclasses/exits.py has class Exit(DefaultExit)

    • -
    • mygame/typeclasses/accounts.py has class Account(DefaultAccount)

    • -
    • mygame/typeclasses/channels.py has class Channel(DefaultChannel)

    • -
    • mygame/typeclasses/scripts.py has class Script(DefaultScript)

    • -
    -
    -

    Notice that the classes in mygame/typeclasses/ are not inheriting from each other. For example, -Character is inheriting from evennia.DefaultCharacter and not from typeclasses.objects.Object. -So if you change Object you will not cause any change in the Character class. If you want that you -can easily just change the child classes to inherit in that way instead; Evennia doesn’t care.

    -
    -

    As seen with our Dragon example, you don’t have to modify these modules directly. You can just make your -own modules and import the base class.

    -
    -

    7.2.1. Examining and defaults

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Evennia base typeclass

    mygame.typeclasses child

    description

    evennia.DefaultObject

    typeclasses.objects.Object

    Everything with a location

    evennia.DefaultCharacter (child of DefaultObject)

    typeclasses.characters.Character

    Player avatars

    evennia.DefaultRoom (child of DefaultObject)

    typeclasses.rooms.Room

    In-game locations

    evennia.DefaultExit (chld of DefaultObject)

    typeclasses.exits.Exit

    Links between rooms

    evennia.DefaultAccount

    typeclasses.accounts.Account

    A player account

    evennia.DefaultChannel

    typeclasses.channels.Channel

    In-game comms

    evennia.DefaultScript

    typeclasses.scripts.Script

    Entities with no location

    +

    The child classes under mygame/typeclasses/ are meant for you to conveniently modify and +work with. Every class inheriting (at any distance) from a Evennia base typeclass is also considered a typeclass.

    +
    from somewhere import Something 
    +from evennia import DefaultScript 
    +
    +class MyOwnClass(Something): 
    +    # not inheriting from an Evennia core typeclass, so this 
    +    # is just a 'normal' Python class inheriting from somewhere
    +    pass 
    +
    +class MyOwnClass2(DefaultScript):
    +    # inherits from one of the core Evennia typeclasses, so 
    +    # this is also considered a 'typeclass'.
    +    pass
    +
    +
    +
    + +

    Notice that the classes in mygame/typeclasses/ are not inheriting from each other. For example, Character is inheriting from evennia.DefaultCharacter and not from typeclasses.objects.Object. So if you change Object you will not cause any change in the Character class. If you want that you can easily just change the child classes to inherit in that way instead; Evennia doesn’t care.

    +

    As seen with our Dragon example, you don’t have to modify these modules directly. You can just make your own modules and import the base class.

    +
    +

    7.2.1. Examining objects

    When you do

    > create/drop giantess:typeclasses.monsters.Monster
     You create a new Monster: giantess.
    @@ -372,19 +391,17 @@ may be more useful to us:

  • Name/key - The name of this thing. The value (#14) is probably different for you. This is the unique ‘primary key’ or dbref for this entity in the database.

  • Typeclass: This show the typeclass we specified, and the path to it.

  • -
  • Location: We are in Limbo. If you moved elsewhere you’ll see that instead. Also the #dbref is shown.

  • -
  • Permissions: Permissions are like the inverse to Locks - they are like keys to unlock access to other things. -The giantess have no such keys (maybe fortunately).

  • -
  • Locks: Locks are the inverse of Permissions - specify what criterion other objects must fulfill in order to -access the giantess object. This uses a very flexible mini-language. For examine, the line examine:perm(Builders) -is read as “Only those with permission Builder or higher can examine this object”. Since we are the superuser -we pass (even bypass) such locks with ease.

  • -
  • Persistent attributes: This allows for storing arbitrary, persistent data on the typeclassed entity. We’ll get -to those in the next section.

  • +
  • Location: We are in Limbo. If you moved elsewhere you’ll see that instead. Also the #dbref of Limbo is shown.

  • +
  • Home: All objects with a location (inheriting from DefaultObject) must have a home location. This is a backup to move the object to if its current location is deleted.

  • +
  • Permissions: Permissions are like the inverse to Locks - they are like keys to unlock access to other things. The giantess have no such keys (maybe fortunately). The Permissions has more info.

  • +
  • Locks: Locks are the inverse of Permissions - specify what criterion other objects must fulfill in order to access the giantess object. This uses a very flexible mini-language. For examine, the line examine:perm(Builders) is read as “Only those with permission Builder or higher can examine this object”. Since we are the superuser we pass (even bypass) such locks with ease. See the Locks documentation for more info.

  • +
  • Persistent attributes: This allows for storing arbitrary, persistent data on the typeclassed entity. We’ll get to those in the next section.

  • -

    Note how the Typeclass line describes exactly where to find the code of this object? This is very useful for -understanding how any object in Evennia works.

    -

    What happens if we don’t specify the typeclass though?

    +

    Note how the Typeclass line describes exactly where to find the code of this object? This is very useful for understanding how any object in Evennia works.

    +
    +
    +

    7.2.2. Default typeclasses

    +

    What happens if we create an object and don’t specify its typeclass though?

    > create/drop box 
     You create a new Object: box.
     
    @@ -401,20 +418,14 @@ You create a new Object: box.
    Typeclass: Object (typeclasses.objects.Object) 
     
    -

    So when you didn’t specify a typeclass, Evennia used a default, more specifically the (so far) empty Object class in -mygame/typeclasses/objects.py. This is usually what you want, especially since you can tweak that class as much -as you like.

    -

    But the reason Evennia knows to fall back to this class is not hard-coded - it’s a setting. The default is -in evennia/settings_default.py, -with the name BASE_OBJECT_TYPECLASS, which is set to typeclasses.objects.Object.

    +

    So when you didn’t specify a typeclass, Evennia used a default, more specifically the (so far) empty Object class in mygame/typeclasses/objects.py. This is usually what you want, especially since you can tweak that class as much as you like.

    +

    But the reason Evennia knows to fall back to this class is not hard-coded - it’s a setting. The default is in evennia/settings_default.py, with the name BASE_OBJECT_TYPECLASS, which is set to typeclasses.objects.Object.

    So if you wanted the creation commands and methods to default to some other class you could -add your own BASE_OBJECT_TYPECLASS line to mygame/server/conf/settings.py. The same is true for all the other -typeclasseses, like characters, rooms and accounts. This way you can change the -layout of your game dir considerably if you wanted. You just need to tell Evennia where everything is.

    +add your own BASE_OBJECT_TYPECLASS line to mygame/server/conf/settings.py. The same is true for all the other typeclasseses, like characters, rooms and accounts. This way you can change the layout of your game dir considerably if you wanted. You just need to tell Evennia where everything is.

    @@ -432,8 +443,7 @@ layout of your game dir considerably if you wanted. You just need to tell Evenni pass -

    This looks quite familiar now - an empty class inheriting from the Evennia base typeclass. As you would expect, -this is also the default typeclass used for creating Characters if you don’t specify it. You can verify it:

    +

    This looks quite familiar now - an empty class inheriting from the Evennia base typeclass (it’s even easier than Object since there is no equvalent ParentObject mixin class here). As you would expect, this is also the default typeclass used for creating Characters if you don’t specify it. You can verify it:

    > examine me
     ------------------------------------------------------------------------------
     Name/key: YourName (#1)
    @@ -461,17 +471,15 @@ Non-Persistent attributes:
     ------------------------------------------------------------------------------
     
    -

    You got a lot longer output this time. You have a lot more going on than a simple Object. Here are some new fields of note:

    +

    Yes, the examine command understands me. You got a lot longer output this time. You have a lot more going on than a simple Object. Here are some new fields of note:

    • Session id(s): This identifies the Session (that is, the individual connection to a player’s game client).

    • Account shows, well the Account object associated with this Character and Session.

    • -
    • Stored/Merged Cmdsets and Commands available is related to which Commands are stored on you. We will -get to them in the next lesson. For now it’s enough to know these consitute all the +

    • Stored/Merged Cmdsets and Commands available is related to which Commands are stored on you. We will get to them in the next lesson. For now it’s enough to know these consitute all the commands available to you at a given moment.

    • Non-Persistent attributes are Attributes that are only stored temporarily and will go away on next reload.

    -

    Look at the Typeclass field and you’ll find that it points to typeclasses.character.Character as expected. -So if we modify this class we’ll also modify ourselves.

    +

    Look at the Typeclass field and you’ll find that it points to typeclasses.character.Character as expected. So if we modify this class we’ll also modify ourselves.

    7.3.1. A method on ourselves

    Let’s try something simple first. Back in mygame/typeclasses/characters.py:

    @@ -481,15 +489,15 @@ So if we modify this class we’ll also modify ourselves.

    (class docstring) """ - str = 10 - dex = 12 - int = 15 + strength = 10 + dexterity = 12 + intelligence = 15 def get_stats(self): """ Get the main stats of this character """ - return self.str, self.dex, self.int + return self.strength, self.dexterity, self.intelligence @@ -505,9 +513,7 @@ So if we modify this class we’ll also modify ourselves.

  • A tuple is written (a, b, c, ...). It cannot be modified once created.

  • -

    We made a new method, gave it a docstring and had it return the RP-esque values we set. It comes back as a -tuple (10, 12, 15). To get a specific value you could specify the index of the value you want, -starting from zero:

    +

    We made a new method, gave it a docstring and had it return the RP-esque values we set. It comes back as a tuple (10, 12, 15). To get a specific value you could specify the index of the value you want, starting from zero:

    > py stats = self.get_stats() ; print(f"Strength is {stats[0]}.")
     Strength is 10.
     
    @@ -516,15 +522,14 @@ Strength is 10.

    7.3.2. Attributes

    So what happens when we increase our strength? This would be one way:

    -
    > py self.str = self.str + 1
    -> py self.str
    +
    > py self.strength = self.str + 1
    +> py self.strength
     11
     
    -

    Here we set the strength equal to its previous value + 1. A shorter way to write this is to use Python’s += -operator:

    -
    > py self.str += 1
    -> py self.str 
    +

    Here we set the strength equal to its previous value + 1. A shorter way to write this is to use Python’s += operator:

    +
    > py self.strength += 1
    +> py self.strength
     12     
     > py self.get_stats()
     (12, 12, 15)
    @@ -536,12 +541,8 @@ operator:

    (10, 12, 15)
    -

    After a reload all our changes were forgotten. When we change properties like this, it only changes in memory, -not in the database (nor do we modify the python module’s code). So when we reloaded, the ‘fresh’ Character -class was loaded, and it still has the original stats we wrote to it.

    -

    In principle we could change the python code. But we don’t want to do that manually every time. And more importantly -since we have the stats hardcoded in the class, every character instance in the game will have exactly the -same str, dex and int now! This is clearly not what we want.

    +

    After a reload all our changes were forgotten. When we change properties like this, it only changes in memory, not in the database (nor do we modify the python module’s code). So when we reloaded, the ‘fresh’ Character class was loaded, and it still has the original stats we wrote in it.

    +

    In principle we could change the python code. But we don’t want to do that manually every time. And more importantly since we have the stats hardcoded in the class, every character instance in the game will have exactly the same str, dex and int now! This is clearly not what we want.

    Evennia offers a special, persistent type of property for this, called an Attribute. Rework your mygame/typeclasses/characters.py like this:

    
    @@ -554,42 +555,38 @@ same str"""
             Get the main stats of this character
             """
    -        return self.db.str, self.db.dex, self.db.int
    +        return self.db.strength, self.db.dexterity, self.db.intelligence
     
    -

    We removed the hard-coded stats and added added .db for every stat. The .db handler makes the stat -into an an Evennia Attribute.

    +

    We removed the hard-coded stats and added added .db for every stat. The .db handler makes the stat into an an Evennia Attribute.

    > reload 
     > py self.get_stats()
     (None, None, None) 
     
    -

    Since we removed the hard-coded values, Evennia don’t know what they should be (yet). So all we get back -is None, which is a Python reserved word to represent nothing, a no-value. This is different from a normal python -property:

    -
    > py self.str
    -AttributeError: 'Character' object has no attribute 'str'
    -> py self.db.str
    +

    Since we removed the hard-coded values, Evennia don’t know what they should be (yet). So all we get back is None, which is a Python reserved word to represent nothing, a no-value. This is different from a normal python property:

    +
    > py me.strength
    +AttributeError: 'Character' object has no attribute 'strength'
    +> py me.db.strength
     (nothing will be displayed, because it's None)
     
    -

    Trying to get an unknown normal Python property will give an error. Getting an unknown Evennia Attribute will -never give an error, but only result in None being returned. This is often very practical.

    -
    > py self.db.str, self.db.dex, self.db.int = 10, 12, 15
    -> py self.get_stats()
    +

    Trying to get an unknown normal Python property will give an error. Getting an unknown Evennia Attribute will never give an error, but only result in None being returned. This is often very practical.

    +

    Next, let us test out assigning those Attributes

    +
    > py me.db.strength, me.db.dexterity, me.db.intelligence = 10, 12, 15
    +> py me.get_stats()
     (10, 12, 15)
     > reload 
    -> py self.get_stats()
    +> py me.get_stats()
     (10, 12, 15)
     
    -

    Now we set the Attributes to the right values. We can see that things work the same as before, also after a -server reload. Let’s modify the strength:

    -
    > py self.db.str += 2 
    +

    Now we set the Attributes to the right values, and they survive a server reload! Let’s modify the strength:

    +
    > py self.db.strength += 2 
     > py self.get_stats()
     (12, 12, 15)
     > reload 
    @@ -597,19 +594,12 @@ server reload. Let’s modify the strength:

    (12, 12, 15)
    -

    Our change now survives a reload since Evennia automatically saves the Attribute to the database for us.

    +

    Also our change now survives a reload since Evennia automatically saves the Attribute to the database for us.

    7.3.3. Setting things on new Characters

    -

    Things a looking better, but one thing remains strange - the stats start out with a value None and we -have to manually set them to something reasonable. In a later lesson we will investigate character-creation -in more detail. For now, let’s give every new character some random stats to start with.

    -

    We want those stats to be set only once, when the object is first created. For the Character, this method -is called at_object_creation.

    - +

    Things are looking better, but one thing remains strange - the stats start out with a value None and we have to manually set them to something reasonable. In a later lesson we will investigate character-creation in more detail. For now, let’s give every new character some random stats to start with.

    +

    We want those stats to be set only once, when the object is first created. For the Character, this method is called at_object_creation.

    # up by the other imports
     import random 
     
    @@ -619,15 +609,15 @@ is called at_object
         """
     
         def at_object_creation(self):       
    -        self.db.str = random.randint(3, 18)
    -        self.db.dex = random.randint(3, 18)
    -        self.db.int = random.randint(3, 18)
    +        self.db.strength = random.randint(3, 18)
    +        self.db.dexterity = random.randint(3, 18)
    +        self.db.intelligence = random.randint(3, 18)
         
         def get_stats(self):
             """
             Get the main stats of this character
             """
    -        return self.db.str, self.db.dex, self.db.int
    +        return self.db.strength, self.db.dexterity, self.db.intelligence
     

    We imported a new module, random. This is part of Python’s standard library. We used random.randint to @@ -637,9 +627,11 @@ set a random value from 3 to 18 to each stat. Simple, but for some classical RPG (12, 12, 15)

    -

    Hm, this is the same values we set before. They are not random. The reason for this is of course that, as said, -at_object_creation only runs once, the very first time a character is created. Our character object was already -created long before, so it will not be called again.

    + +

    Hm, this is the same values we set before. They are not random. The reason for this is of course that, as said, at_object_creation only runs once, the very first time a character is created. Our character object was already created long before, so it will not be called again.

    It’s simple enough to run it manually though:

    > self.at_object_creation()
     > py self.get_stats()
    @@ -656,21 +648,22 @@ created long before, so it will not be called again.

    7.3.4. Updating all Characters in a loop

    -

    Needless to say, for your game you are wise to have a feel for what you want to go into the at_object_creation hook -before you create a lot of objects (characters in this case). But should it come to that you don’t want to have to -go around and re-run the method on everyone manually. For the Python beginner, doing this will also give a chance to -try out Python loops. We try them out in multi-line Python mode:

    + +

    Needless to say, you are wise to have a feel for what you want to go into the at_object_creation hook before you create a lot of objects (characters in this case).

    +

    Luckily you only need to update objects once, and you don’t have to go around and re-run the at_object_creation method on everyone manually. For this we’ll try out a Python loop. Let’s go into multi-line Python mode:

    > py
    -> for a in [1, 2, "foo"]:     >     print(a)
    +> for a in [1, 2, "foo"]:   
    +>     print(a)
     1
     2
     foo
     
    -

    A python for-loop allows us to loop over something. Above, we made a list of two numbers and a string. In -every iteration of the loop, the variable a becomes one element in turn, and we print that.

    -

    For our list, we want to loop over all Characters, and want to call .at_object_creation on each. This is how -this is done (still in python multi-line mode):

    +

    A python for-loop allows us to loop over something. Above, we made a list of two numbers and a string. In every iteration of the loop, the variable a becomes one element in turn, and we print that.

    +

    For our list, we want to loop over all Characters, and want to call .at_object_creation on each. This is how this is done (still in python multi-line mode):

    > from typeclasses.characters import Character
     > for char in Character.objects.all()
     >     char.at_object_creation()
    @@ -678,7 +671,7 @@ this is done (still in python multi-line mode):

    We import the Character class and then we use .objects.all() to get all Character instances. Simplified, .objects is a resource from which one can query for all Characters. Using .all() gets us a listing @@ -693,19 +686,13 @@ Closing the Python console.

    7.4. Extra Credits

    -

    This principle is the same for other typeclasses. So using the tools explored in this lesson, try to expand -the default room with an is_dark flag. It can be either True or False. -Have all new rooms start with is_dark = False and make it so that once you change it, it survives a reload. +

    This principle is the same for other typeclasses. So using the tools explored in this lesson, try to expand the default room with an is_dark flag. It can be either True or False. Have all new rooms start with is_dark = False and make it so that once you change it, it survives a reload. Oh, and if you created any other rooms before, make sure they get the new flag too!

    7.5. Conclusions

    -

    In this lesson we created database-persistent dragons by having their classes inherit from one Object, one -of Evennia’s typeclasses. We explored where Evennia looks for typeclasses if we don’t specify the path -explicitly. We then modified ourselves - via the Character class - to give us some simple RPG stats. This -led to the need to use Evennia’s Attributes, settable via .db and to use a for-loop to update ourselves.

    -

    Typeclasses are a fundamental part of Evennia and we will see a lot of more uses of them in the course of -this tutorial. But that’s enough of them for now. It’s time to take some action. Let’s learn about Commands.

    +

    In this lesson we created database-persistent dragons by having their classes inherit from one Object, one of Evennia’s typeclasses. We explored where Evennia looks for typeclasses if we don’t specify the path explicitly. We then modified ourselves - via the Character class - to give us some simple RPG stats. This led to the need to use Evennia’s Attributes, settable via .db and to use a for-loop to update ourselves.

    +

    Typeclasses are a fundamental part of Evennia and we will see a lot of more uses of them in the course of this tutorial. But that’s enough of them for now. It’s time to take some action. Let’s learn about Commands.

    diff --git a/docs/1.0-dev/Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Part1-Intro.html b/docs/1.0-dev/Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Part1-Intro.html index f9270633e8..725fb57b37 100644 --- a/docs/1.0-dev/Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Part1-Intro.html +++ b/docs/1.0-dev/Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Part1-Intro.html @@ -200,6 +200,7 @@ these concepts in the context of Evennia before.

  • 6. Overview of the Evennia library
  • 7. Making objects persistent
      diff --git a/docs/1.0-dev/Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Python-basic-introduction.html b/docs/1.0-dev/Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Python-basic-introduction.html index 4c9d987d27..30dd149495 100644 --- a/docs/1.0-dev/Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Python-basic-introduction.html +++ b/docs/1.0-dev/Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Python-basic-introduction.html @@ -198,7 +198,7 @@ This is a good idea! @@ -242,21 +242,24 @@ trouble, use the Evennia web client.

      What happened here was that we assigned the string "awesome sauce" to a variable we chose to name a. In the next statement, Python remembered what a was and we passed that into format() -to get the output. If you replaced the value of a with something else in between, that would be printed -instead.

      +to get the output. If you replaced the value of a with something else in between, that would be printed instead.

      Here’s the stat-example again, moving the stats to variables (here we just set them, but in a real game they may be changed over time, or modified by circumstance):

      > py stren, dext, intel = 13, 14, 8 ; print("STR: {}, DEX: {}, INT: {}".format(stren, dext, intel))
       STR: 13, DEX: 14, INT: 8
       
      -

      The point is that even if the values of the stats change, the print() statement would not change - it just keeps -pretty-printing whatever is given to it.

      +

      The point is that even if the values of the stats change, the print() statement would not change - it just keeps pretty-printing whatever is given to it.

      +

      You can also use named markers, like this:

      +
       > py print("STR: {stren}, INT: {intel}, STR again: {stren}".format(dext=10, intel=18, stren=9))
      + STR: 9, INT: 18, Str again: 9
      +
      +
      +

      the key=value pairs we add are called keyword arguments for the format() method. Each named argument will go to the matching {key} in the string. When using keywords, the order we add them doesn’t matter. We have no {dext} and two {stren} in the string, and that works fine.

  • 3.2.2. f-strings

    -

    Using .format() is convenient (and there is a lot more -you can do with it). But the f-string can be even more convenient. An +

    Using .format() is convenient (and there is a lot more you can do with it). But the f-string can be even more convenient. An f-string looks like a normal string … except there is an f front of it, like this:

    f"this is now an f-string."
     
    @@ -266,7 +269,7 @@ f-string looks like a normal string … except there is an a variable directly into the f-string using {a}. Fewer parentheses to +

    We insert that a variable directly into the f-string using {a}. Fewer parentheses to remember and arguable easier to read as well.

    > py stren, dext, intel = 13, 14, 8 ; print(f"STR: {stren}, DEX: {dext}, INT: {intel}")
     STR: 13, DEX: 14, INT: 8
    @@ -291,7 +294,7 @@ gives the normal text color. You can also use RGB (Red-Green-Blue) values from 0
     

    If you don’t see the expected color, your client or terminal may not support Xterm256 (or color at all). Use the Evennia webclient.

    -

    Use the commands color ansi or color xterm to see which colors are available. Experiment!

    +

    Use the commands color ansi or color xterm to see which colors are available. Experiment! You can also read a lot more in the Colors documentation.

    @@ -326,21 +329,15 @@ Hello World

    If you make some error (we’ll cover how to handle errors below), fix the error in the module and run the reload command in-game for your changes to take effect.

    So importing world.test actually means importing world/test.py. Think of the period . as -replacing / (or \ for Windows) in your path. The .py ending of test.py is also never -included in this “Python-path”, but only files with that ending can be imported this way. -Where is mygame in that Python-path? The answer is that Evennia has already told Python that -your mygame folder is a good place to look for imports. So we don’t include mygame in the -path - Evennia handles this for us.

    +replacing / (or \ for Windows) in your path.

    +

    The .py ending of test.py is never included in this “Python-path”, but only files with that ending can be imported this way. Where is mygame in that Python-path? The answer is that Evennia has already told Python that your mygame folder is a good place to look for imports. So we should not include mygame in the path - Evennia handles this for us.

    When you import the module, the top “level” of it will execute. In this case, it will immediately print “Hello World”.

    Now try to run this a second time:

    > py import world.test
     
    -

    You will not see any output this second time or any subsequent times! This is not a bug. Rather -it is because of how Python importing works - it stores all imported modules and will -avoid importing them more than once. So your print will only run the first time, when the module -is first imported.

    +

    You will not see any output this or any subsequent times! This is not a bug. Rather it is because of how Python importing works - it stores all imported modules and will avoid importing them more than once. So your print will only run the first time, when the module is first imported.

    Try this:

    > reload
     
    @@ -354,8 +351,7 @@ Hello World! import it anew. You’d have to do this every time you wanted the print to show though, which is not very useful.

    -

    We’ll get back to more advanced ways to import code in later tutorial sections - this is an -important topic. But for now, let’s press on and resolve this particular problem.

    +

    We’ll get back to more advanced ways to import code in a later lesson - this is an important topic. But for now, let’s press on and resolve this particular problem.

    3.3.1. Our first own function

    @@ -528,8 +524,8 @@ the room it is in.

    A mirror should appear in your location.

    > look mirror
    @@ -585,7 +581,7 @@ when you want to do some quick testing. But you can also start a full multi-line
     inside Evennia.

    > py
     Evennia Interactive Python mode
    -Python 3.7.1 (default, Oct 22 2018, 11:21:55)
    +Python 3.11.0 (default, Nov 22 2022, 11:21:55)
     [GCC 8.2.0] on Linux
     [py mode - quit() to exit]
     
    @@ -600,14 +596,12 @@ Hello World [py mode - quit() to exit]
    -

    Note that we didn’t need to put py in front now. The system will also echo your input (that’s the bit after -the >>>). For brevity in this tutorual we’ll turn the echo off. First exit py and then start again with the -/noecho flag.

    +

    Note that we didn’t need to put py in front now. The system will also echo your input (that’s the bit after the >>>). For brevity in this tutorual we’ll turn the echo off. First exit py and then start again with the /noecho flag.

    > quit()
     Closing the Python console.
     > py/noecho
     Evennia Interactive Python mode (no echoing of prompts)
    -Python 3.7.1 (default, Oct 22 2018, 11:21:55)
    +Python 3.11.0 (default, Nov 22 2022, 11:21:56)
     [GCC 8.2.0] on Linux
     [py mode - quit() to exit]
     
    @@ -617,13 +611,13 @@ Python 3.7.1 (default, Oct 22 2018, 11:21:55)
    • Start with py.

    • Use py/noecho if you don’t want your input to be echoed for every line.

    • -
    • All your inputs will now be interpreted as Python code.

    • +
    • All your inputs will now be interpreted as Python code.

    • Exit with quit().

    We can now enter multi-line Python code:

    > a = "Test"
    -> print(f"This is a {a}."}
    +> print(f"This is a {a}.")
     This is a Test.
     
    @@ -643,8 +637,7 @@ of the block with indention. So the next line must be manually indented (4 space for Python to know it’s part of the function body.

  • We expand the hello_world function with another argument txt. This allows us to send any text, not just “Hello World” over and over.

  • -
  • To tell py that no more lines will be added to the function body, we end with an empty input. When -the normal prompt on how to exit returns, we know we are done.

  • +
  • To tell py that no more lines will be added to the function body, we end with an empty input. When the normal prompt returns, we know we are done.

  • Now we have defined a new function. Let’s try it out:

    > hello_world(me, "Hello world to me!")
    @@ -731,8 +724,7 @@ Python code, we need to save it in a Python module, like we did for 
    -

    To that end we also created a first new Python module in the mygame/ game dir, then imported and used it. -Now let’s look at the rest of the stuff you’ve got going on inside that mygame/ folder …

    +

    To that end we also created a first new Python module in the mygame/ game dir, then imported and used it. Now let’s look at the rest of the stuff you’ve got going on inside that mygame/ folder …

    diff --git a/docs/1.0-dev/Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Python-classes-and-objects.html b/docs/1.0-dev/Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Python-classes-and-objects.html index 25165a7f31..f05259e4f5 100644 --- a/docs/1.0-dev/Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Python-classes-and-objects.html +++ b/docs/1.0-dev/Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Python-classes-and-objects.html @@ -119,16 +119,14 @@ We have also taken a look at what our game dir looks and what is where. Now we’ll start to use it.

    5.1. Importing things

    -

    No one writes something as big as an online game in one single huge file. Instead one breaks up the -code into separate files (modules). Each module is dedicated to different purposes. Not only does -it make things cleaner, organized and easier to understand. It also makes it easier to re-use code - -you just import the resources you need and know you only get just what you requested. This makes -it much easier to find errors and to know what code is good and which has issues.

    +

    In a previous lesson we already learned how to import resources into our code. Now we’ll dive a little deeper.

    +

    No one writes something as big as an online game in one single huge file. Instead one breaks up the code into separate files (modules). Each module is dedicated to different purposes. Not only does it make things cleaner, organized and easier to understand.

    +

    Splitting code also makes it easier to re-use - you just import the resources you need and know you only get just what you requested. This makes it easier to spot errors and to know what code is good and which has issues.

    Evennia itself uses your code in the same way - you just tell it where a particular type of code is, and it will import and use it (often instead of its defaults).

    -

    We have already successfully imported things, for example:

    +

    Here’s a familiar example:

    > py import world.test ; world.test.hello_world(me)
     Hello World!
     
    @@ -156,10 +154,7 @@ not, make it so):

  • Anything on a line after a # is a comment, ignored by Python

  • -

    The python_path describes the relation between Python resources, both between and inside -Python modules (that is, files ending with .py). A python-path separates each part of the -path . and always skips the .py file endings. Also, Evennia already knows to start looking -for python resources inside mygame/ so this should never be specified. Hence

    +

    To reiterate, the python_path describes the relation between Python resources, both between and inside Python modules (that is, files ending with .py). Paths use . and always skips the .py file endings. Also, Evennia already knows to start looking for python resources inside mygame/ so this should never be included.

    import world.test
     
    @@ -169,7 +164,7 @@ this module to get to the function you want:

    Using import like this means that you have to specify the full world.test every time you want -to get to your function. Here’s a more powerful form of import:

    +to get to your function. Here’s an alternative:

    from world.test import hello_world
     
    @@ -237,6 +232,12 @@ imports at the top, resources that are then used by all code in that module.

    """ from evennia import DefaultObject +class ObjectParent: + """ + class docstring + """ + pass + class Object(DefaultObject): """ class docstring @@ -246,28 +247,24 @@ imports at the top, resources that are then used by all code in that module.

    The real file is much longer but we can ignore the multi-line strings (""" ... """). These serve as documentation-strings, or docstrings for the module (at the top) and the class below.

    Below the module doc string we have the import. In this case we are importing a resource from the core evennia library itself. We will dive into this later, for now we just treat this as a black box.

    -

    Next we have a class named Object, which inherits from DefaultObject. This class doesn’t -actually do anything on its own, its only code (except the docstring) is pass which means, -well, to pass and don’t do anything.

    -

    We will get back to this module in the next lesson. First we need to do a -little detour to understand what a ‘class’, an ‘object’ or ‘instance’ is. These are fundamental -things to understand before you can use Evennia efficiently.

    +

    Next we have an empty class named ObjectParent. It doesn’t do anything, its only code (except the docstring) is pass which means, well, to pass and don’t do anything. Since it also doesn’t inherit from anything, it’s just an empty container. We will not concern ourselves with it for this tutorial.

    +

    The class named Object_ inherits_ from ObjectParent and DefaultObject. Since we see that ObjectParent is empty, what is interesting is DefaultObject. Again, the Object class doesn’t +actually do anything on its own right now, but because of it being a child of DefaultObject, it’s actually providing a lot of functionality! If this is confusing, read on.

    +

    We will get back to this module in the next lesson. First we need to do a little detour to understand what a ‘class’, an ‘object’ or ‘instance’ is. These are fundamental things to understand before you can use Evennia efficiently.

    5.2.1. Classes and instances

    -

    A ‘class’ can be seen as a ‘template’ for a ‘type’ of object. The class describes the basic functionality -of everyone of that class. For example, we could have a class Monster which has resources for moving itself -from room to room.

    +

    A ‘class’ can be seen as a ‘template’ for a ‘type’ of object. The class describes the basic functionality of everyone of that class. For example, we could have a class Monster which has resources for moving itself from room to room.

    Open a new file mygame/typeclasses/monsters.py. Add the following simple class:

    
     class Monster:
    @@ -288,11 +285,11 @@ back to the keyTerms

    • A class is a code template describing a ‘type’ of something

    • -
    • An object is an instance of a class. Like using a mold to cast in soldiers, one class can be instantiated into any number of object-instances.

    • +
    • An object is an instance of a class. Like using a mold to cast tin soldiers, one class can be instantiated into any number of object-instances. Each instance does not need to be identical (much like each tin soldier can be painted differently).

    A class is just a template. Before it can be used, we must create an instance of the class. If -Monster is a class, then an instance is Fluffy, the individual red dragon. You instantiate +Monster is a class, then an instance is Fluffy, a specific dragon individual. You instantiate by calling the class, much like you would a function:

    fluffy = Monster()
     
    @@ -319,8 +316,7 @@ Monster is moving!

    We now have two dragons and they’ll hang around until with call quit() to exit this Python -instance. We can have them move as many times as we want. But no matter how many dragons we -create, they will all show the same printout since key is always fixed as “Monster”.

    +instance. We can have them move as many times as we want. But no matter how many dragons we create, they will all show the same printout since key is always fixed as “Monster”.

    Let’s make the class a little more flexible:

    
     class Monster:
    @@ -358,13 +354,11 @@ fluffy.move_around()
     Fluffy is moving!
     
    -

    Now we passed "Fluffy" as an argument to the class. This went into __init__ and set self.key, which we -later used to print with the right name! Again, note that we didn’t include self when calling.

    +

    Now we passed "Fluffy" as an argument to the class. This went into __init__ and set self.key, which we later used to print with the right name!

    5.2.2. What’s so good about objects?

    -

    So far all we’ve seen a class do is to behave our first hello_world function but more complex. We -could just have made a function:

    +

    So far all we’ve seen a class do is to behave like our first hello_world function but being more complex. We could just have made a function:

         def monster_move_around(key):
             print(f"{key} is moving!")
     
    @@ -372,14 +366,13 @@ could just have made a function:

    The difference between the function and an instance of a class (the object), is that the object retains state. Once you called the function it forgets everything about what you called it with last time. The object, on the other hand, remembers changes:

    -
    > fluffy.key = "Cuddly"
    +
    > fluffy.key = "Fluffy, the red dragon"
     > fluffy.move_around()
    -Cuddly is moving!
    +Fluffy, the red dragon is moving!
     
    -

    The fluffy object’s key was changed to “Cuddly” for as long as it’s around. This makes objects -extremely useful for representing and remembering collections of data - some of which can be other -objects in turn:

    +

    The fluffy object’s key was changed for as long as it’s around. This makes objects extremely useful for representing and remembering collections of data - some of which can be other +objects in turn. Some examples:

    • A player character with all its stats

    • A monster with HP

    • @@ -393,8 +386,7 @@ objects in turn:

    5.2.3. Classes can have children

    -

    Classes can inherit from each other. A “child” class will inherit everything from its “parent” class. But if -the child adds something with the same name as its parent, it will override whatever it got from its parent.

    +

    Classes can inherit from each other. A “child” class will inherit everything from its “parent” class. But if the child adds something with the same name as its parent, it will override whatever it got from its parent.

    Let’s expand mygame/typeclasses/monsters.py with another class:

    
     class Monster:
    @@ -411,7 +403,7 @@ the child adds something with the same name as its parent, it will override<
     
     class Dragon(Monster):
         """
    -    This is a dragon-specific monster.
    +    This is a dragon monster.
         """
     
         def move_around(self):
    @@ -425,15 +417,14 @@ the child adds something with the same name as its parent, it will override<
     
     
    -

    We added some docstrings for clarity. It’s always a good idea to add doc strings; you can do so also for methods, -as exemplified for the new firebreath method.

    +

    We added some docstrings for clarity. It’s always a good idea to add doc strings; you can do so also for methods, as exemplified for the new firebreath method.

    We created the new class Dragon but we also specified that Monster is the parent of Dragon but adding the parent in parenthesis. class Classname(Parent) is the way to do this.

    -

    Let’s try out our new class. First reload the server and the do

    +

    Let’s try out our new class. First reload the server and then:

    > py
     > from typeclasses.monsters import Dragon
     > smaug = Dragon("Smaug")
    @@ -443,12 +434,8 @@ Smaug flies through the air high above!
     Smaug breathes fire!
     
    -

    Because we didn’t implement __init__ in Dragon, we got the one from Monster instead. But since we -implemented our own move_around in Dragon, it overrides the one in Monster. And firebreath is only -available for Dragons of course. Having that on Monster would not have made much sense, since not every monster -can breathe fire.

    -

    One can also force a class to use resources from the parent even if you are overriding some of it. This is done -with the super() method. Modify your Dragon class as follows:

    +

    Because we didn’t (re)implement __init__ in Dragon, we got the one from Monster. We did implement our own move_around in Dragon, so it overrides the one in Monster. And firebreath is only available for Dragons. Having that on Monster would not have made much sense, since not every monster can breathe fire.

    +

    One can also force a class to use resources from the parent even if you are overriding some of it. This is done with the super() method. Modify your Dragon class as follows:

    # ...
     
     class Dragon(Monster):
    @@ -461,11 +448,10 @@ with the super()
    -

    Keep Monster and the firebreath method, # ... indicates the rest of the code is untouched.

    +

    Keep Monster and the firebreath method. The # ... above indicates the rest of the code is unchanged.

    -

    The super().move_around() line means that we are calling move_around() on the parent of the class. So in this -case, we will call Monster.move_around first, before doing our own thing.

    -

    Now reload the server and then:

    +

    The super().move_around() line means that we are calling move_around() on the parent of the class. So in this case, we will call Monster.move_around first, before doing our own thing.

    +

    To see, reload the server and then:

    > py
     > from typeclasses.monsters import Dragon
     > smaug = Dragon("Smaug")
    @@ -474,19 +460,14 @@ Smaug is moving!
     The world trembles.
     
    -

    We can see that Monster.move_around() is calls first and prints “Smaug is moving!”, followed by the extra bit -about the trembling world we added in the Dragon class.

    -

    Inheritance is very powerful because it allows you to organize and re-use code while only adding the special things -you want to change. Evennia uses this concept a lot.

    +

    We can see that Monster.move_around() is called first and prints “Smaug is moving!”, followed by the extra bit about the trembling world from the Dragon class.

    +

    Inheritance is a powerful concept. It allows you to organize and re-use code while only adding the special things you want to change. Evennia uses this a lot.

    5.3. Summary

    -

    We have created our first dragons from classes. We have learned a little about how you instantiate a class -into an object. We have seen some examples of inheritance and we tested to override a method in the parent -with one in the child class. We also used super() to good effect.

    -

    We have used pretty much raw Python so far. In the coming lessons we’ll start to look at the extra bits that Evennia -provides. But first we need to learn just where to find everything.

    +

    We have created our first dragons from classes. We have learned a little about how you instantiate a class into an object. We have seen some examples of inheritance and we tested to override a method in the parent with one in the child class. We also used super() to good effect.

    +

    We have used pretty much raw Python so far. In the coming lessons we’ll start to look at the extra bits that Evennia provides. But first we need to learn just where to find everything.

    diff --git a/docs/1.0-dev/Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Tutorial-World.html b/docs/1.0-dev/Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Tutorial-World.html index 94992769f5..3251ded0ea 100644 --- a/docs/1.0-dev/Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Tutorial-World.html +++ b/docs/1.0-dev/Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Tutorial-World.html @@ -140,7 +140,8 @@ Both if you are triumphant or if you use the

    2.1. Gameplay

    -

    the castle off the moor

    +

    the castle off the moor +(image by Griatch)

    To get into the mood of this miniature quest, imagine you are an adventurer out to find fame and fortune. You have heard rumours of an old castle ruin by the coast. In its depth a warrior princess was buried together with her powerful magical weapon - a valuable prize, if it’s true. Of course diff --git a/docs/1.0-dev/Setup/Installation.html b/docs/1.0-dev/Setup/Installation.html index 90318b0f77..30622372c6 100644 --- a/docs/1.0-dev/Setup/Installation.html +++ b/docs/1.0-dev/Setup/Installation.html @@ -123,7 +123,7 @@

  • Windows: In the installer, make sure you select add python to path. If you have multiple versions of Python installed, use py command instead of python to have Windows automatically use the latest.

  • -
  • Using a light-weight Python virtual environment _ is optional, but highly recommended in order to keep your Evennia installation independent from the system libraries. This comes with Python.

  • +
  • Using a light-weight Python virtual environment is optional, but highly recommended in order to keep your Evennia installation independent from the system libraries. Using virtualenvs is common Python praxis.

  • Don’t install Evennia as administrator or superuser.

  • If you run into trouble, see installation troubleshooting.

  • @@ -131,7 +131,7 @@
    pip install evennia
     
    -

    Optional: If you use a contrib that warns you that it needs additional packages, you can +

    Optional: If you use a contrib that warns you that it needs additional packages, you can install all extra dependencies with

    pip install evennia[extra]
     
    @@ -140,23 +140,25 @@ install all extra dependencies with

    pip install --upgrade evennia
     
    -

    Once installed, make sure the evennia command works. Use evennia -h for usage help. If you are using a virtualenv, make sure it’s active whenever you need to use the evennia command.

    +
    +

    Windows users only: You now need to run python -m evennia once. This should permanently make the evennia command available in your environment.

    +
    +

    Once installed, make sure the evennia command works. Use evennia -h for usage help. If you are using a virtualenv, make sure it’s active whenever you need to use the evennia command later.

    You can also clone Evennia from github or use docker. Some users have also experimented with installing Evennia on Android.

    Initialize a new game

    -
    -

    Windows users: You need to first run python -m evennia once. This should permanently add the evennia launcher to your environment, making the evennia command available.

    -
    -

    Use cd to enter a folder where you want to do your game development. Here (and in -the rest of the Evennia documentation) we call this folder mygame, but you should of course -name your game whatever you like.

    +

    We will create a new “game dir” for you do create your game in. Here (and in +the rest of the Evennia documentation) we refer to this game dir as mygame, but you should of course name your game whatever you like.

    evennia --init mygame
     

    This will create a new folder mygame (or whatever you chose) in your current location. This contains empty templates and all the default settings needed to start the server.

    +
    +

    The game dir doesn’t need to have the exact same name as your game. You can set the name of your game later by editing mygame/server/conf/settings.py.

    +

    Start the new game

    @@ -168,7 +170,7 @@ evennia migrate
    evennia start
     
    -

    Set your user-name and password when prompted. This will be the “god user” or “superuser” in-game. The email is optional.

    +

    Set your user-name and password when prompted. This will be the “god user” or “super user” in-game. The email is optional.

    You can also automate the creation of the super user.

    @@ -189,6 +191,7 @@ evennia migrate
    evennia stop
     
    +

    See Server start-stop-reload page for more details.

    See server logs

    @@ -208,18 +211,17 @@ evennia migrate

    Server configuration

    -

    The server configuration file is mygame/server/settings.py. It’s empty by default. Copy and change only the settings you want from the default settings file.

    +

    The server configuration file is mygame/server/settings.py. It’s empty by default. Copy and change only the settings you want from the default settings file. See the Settings documentation for more info.

    Register with the Evennia Game Index (optional)

    You can let the world know that you are working on a new Evennia-based game by -registering your server with the Evennia game index. You don’t have to be -open for players to do this - you just mark your game as closed and “pre-alpha”.

    +registering your server with the Evennia game index.

    evennia connections 
     
    -

    See here for more instructions and please check out the index -beforehand to make sure you don’t pick a game name that is already taken - be nice!

    +

    Just follow the prompts. You don’t have to be open for players to do this - you just mark your game as closed and “pre-alpha”.

    +

    See here for more instructions and please check out the index beforehand to make sure you don’t pick a game name that is already taken - be nice!

    The Next steps

    diff --git a/docs/1.0-dev/Setup/Settings-Default.html b/docs/1.0-dev/Setup/Settings-Default.html index 8b597feb2c..4663645141 100644 --- a/docs/1.0-dev/Setup/Settings-Default.html +++ b/docs/1.0-dev/Setup/Settings-Default.html @@ -18,7 +18,7 @@ - + @@ -62,7 +62,7 @@

    Table of Contents

    diff --git a/docs/1.0-dev/Setup/Setup-Overview.html b/docs/1.0-dev/Setup/Setup-Overview.html index 73313e54c9..55a56d6533 100644 --- a/docs/1.0-dev/Setup/Setup-Overview.html +++ b/docs/1.0-dev/Setup/Setup-Overview.html @@ -62,8 +62,8 @@

    Table of Contents