mirror of
https://github.com/evennia/evennia.git
synced 2026-03-30 04:27:16 +02:00
Updated ReST documentation.
This commit is contained in:
parent
d885ef6ab3
commit
b15d1fa683
8 changed files with 518 additions and 61 deletions
|
|
@ -6,6 +6,7 @@ Alphabetical page index
|
|||
:titlesonly:
|
||||
|
||||
wiki/AddingCommandTutorial
|
||||
wiki/AddingObjectTypeclassTutorial
|
||||
wiki/AdminDocs
|
||||
wiki/ApacheConfig
|
||||
wiki/AsyncProcess
|
||||
|
|
@ -17,6 +18,7 @@ Alphabetical page index
|
|||
wiki/BuilderDocs
|
||||
wiki/BuildingPermissions
|
||||
wiki/BuildingQuickstart
|
||||
wiki/Caches
|
||||
wiki/ChoosingAnSQLServer
|
||||
wiki/CodingIntroduction
|
||||
wiki/CodingUtils
|
||||
|
|
|
|||
178
docs/sphinx/source/wiki/AddingObjectTypeclassTutorial.rst
Normal file
178
docs/sphinx/source/wiki/AddingObjectTypeclassTutorial.rst
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
Creating your own object classes
|
||||
================================
|
||||
|
||||
Evennia comes with a few very basic classes of in-game entities:
|
||||
|
||||
::
|
||||
|
||||
Object
|
||||
|
|
||||
Character
|
||||
Room
|
||||
Exit
|
||||
|
||||
So the more specific object-types are just children of the basic
|
||||
``Object`` class (technically these are all
|
||||
`Typeclasses <Typeclassed.html>`_ entities, but for this tutorial, just
|
||||
treat them as normal Python classes).
|
||||
|
||||
For your own game you will most likely want to expand on these very
|
||||
simple beginnings. It's normal to want your Characters to have various
|
||||
attributes. Maybe Rooms should hold extra information or even *all*
|
||||
Objects in your game should have properties not included in basic
|
||||
Evennia.
|
||||
|
||||
First a brief overview of how Evennia handles its object classes. The
|
||||
default classes are defined under ``src/objects/objects.py``. You can
|
||||
look at them there or you can bring up a Python prompt and interactively
|
||||
examine ``ev.Object``, ``ev.Room`` etc.
|
||||
|
||||
You will create your own object classes in ``game/gamesrc/objects``. You
|
||||
should normally inherit from the default classes (normal Python class
|
||||
inheritance) and go from there. Once you have a working new class you
|
||||
can immediately start to create objects in-game inheriting from that
|
||||
class.
|
||||
|
||||
If you want to change the *default* object classes, there is one more
|
||||
step. Evennia's default commands and internal creation mechanisms look
|
||||
at a range of variables in your ``settings.py`` file to determine which
|
||||
are the "default" classes. These defaults are used by the vanilla
|
||||
creation commands if you don't specify the typeclass specifically. They
|
||||
are also used as a fallback by Evennia if there are errors in other
|
||||
typeclasses, so make sure that your new default class is bug-free.
|
||||
|
||||
The following sections spells this out more explicitly.
|
||||
|
||||
Create a new Typeclass
|
||||
----------------------
|
||||
|
||||
This is the simplest case. Say you want to create a new "Heavy" object
|
||||
that characters should not have the ability to pick up.
|
||||
|
||||
#. Go to ``game/gamesrc/objects/``. It should already contain a
|
||||
directory ``examples/``.
|
||||
#. Create a new module here, named ``heavy.py``. Alternatively you can
|
||||
copy ``examples/object.py`` up one level and rename that file to
|
||||
``heavy.py`` instead - you will then have a template to start from.
|
||||
#. Code away in the ``heavy.py`` module, implementing the chair
|
||||
functionality. See `Objects <Objects.html>`_ for more details and the
|
||||
example class below. Let's call the typeclass simply ``Heavy``.
|
||||
#. Once you are done, log into the game with a build-capable account and
|
||||
do ``@create/drop rock:heavy.Heavy`` to drop a new heavy "rock"
|
||||
object in your location. Note that you have to log in as a
|
||||
non-superuser (i.e. not as User #1) when trying to get the rock in
|
||||
order to see its heavy effects.
|
||||
|
||||
That's it. Below is a ``Heavy`` Typeclass that you could try. Note that
|
||||
the `lock <Locks.html>`_ and `Attribute <Attribute.html>`_ here set in
|
||||
the typeclass could just as well have been set using commands in-game,
|
||||
so this is a *very* simple example.
|
||||
|
||||
::
|
||||
|
||||
# file game/gamesrc/objects/heavy.py
|
||||
from ev import Object
|
||||
|
||||
class Heavy(Object):
|
||||
"Heavy object"
|
||||
at_object_creation(self):
|
||||
"Called whenever a new object is created"
|
||||
# lock the object down by default
|
||||
self.locks.add("get:false()")
|
||||
# the default "get" command looks for this Attribute in order
|
||||
# return a customized error message (we just happen to know
|
||||
# this, you'd have to look at the code of the 'get' command to
|
||||
# find out).
|
||||
self.db.get_err_msg = "This is too heavy for you to pick up."
|
||||
|
||||
Change Default Rooms, Exits, Character Typeclass
|
||||
------------------------------------------------
|
||||
|
||||
This is only slightly more complex than creating any other Typeclass. In
|
||||
fact it only includes one extra step - telling Evennia to use the new
|
||||
default.
|
||||
|
||||
Let's say we want to change Rooms to use our new typeclass ``MyRoom``.
|
||||
|
||||
#. Create a new module in ``game/gamesrc/objects/myroom.py`` and code
|
||||
your ``MyRoom`` typeclass as described in the previous section. Make
|
||||
sure to test it by digging a few rooms of this class (e.g.
|
||||
``@dig Hall:myroom.MyRoom``).
|
||||
#. Once you are sure the new class works as it should, edit
|
||||
``game/settings.py`` and add
|
||||
``BASE_ROOM_TYPECLASS="game.gamesrc.objects.myroom.MyRoom"``.
|
||||
#. Reload Evennia.
|
||||
|
||||
For example the ``@dig`` and ``@tunnel`` commands will henceforth use
|
||||
this new default when digging new rooms whenever you don't give a
|
||||
typeclass explicitly. For the other sub-types, change
|
||||
``BASE_CHARACTER_TYPECLASS`` (used by character creation commands) and
|
||||
``BASE_EXIT_TYPECLASS`` (used by ``@dig``/``@tunnel`` etc) respectively.
|
||||
|
||||
Change the default Object Typeclass
|
||||
-----------------------------------
|
||||
|
||||
Changing the root ``Object`` class works identically to changing the
|
||||
``Character``, ``Room`` or ``Exit`` typeclass. After having created your
|
||||
new typeclass, set ``settings.BASE_EXIT_TYPECLASS`` to point to your new
|
||||
class. Let's say you call your new default ``Object`` class
|
||||
``MyObject``.
|
||||
|
||||
There however one important further thing to remember: ``Characters``,
|
||||
``Rooms`` and ``Exits`` will still inherit from the *old* ``Object`` at
|
||||
this point (not ``MyObject``). This is by design - depending on your
|
||||
type of game, you may not need some or all of these subclasses to
|
||||
inherit any of the new stuff you put in ``MyObject``.
|
||||
|
||||
If you do want that however, you need to also overload these subclasses.
|
||||
For each of the ``Character``, ``Room`` and ``Exit`` you want to
|
||||
customize, do the following:
|
||||
|
||||
#. Create a new module in ``game/gamesrc/``, e.g. ``mycharacter.py``
|
||||
etc. A good flexible solution for overloading only parts of the
|
||||
default is to make inheriting classes *multi-inherited* (see below).
|
||||
As a place-holder you can make the class empty for now (just put
|
||||
``pass`` in it).
|
||||
#. In your ``settings.py`` file, add and define
|
||||
``BASE_CHARACTER_TYPECLASS``, ``BASE_ROOM_TYPECLASS`` and
|
||||
``BASE_EXIT_TYPECLASS`` to point to your new typeclasses.
|
||||
#. Reload Evennia.
|
||||
|
||||
This will give you maximum flexibility with creating and expanding your
|
||||
own types of rooms, characters and exit objects (or not). Below is an
|
||||
example of a new ``myroom.py``:
|
||||
|
||||
::
|
||||
|
||||
# file gamesrc/objects/myroom.py
|
||||
from ev import Object
|
||||
from gamesrc.objects.myobject import MyObject
|
||||
# we use multi-inheritance, this will primarily use MyObject,
|
||||
# falling back to the default Object for things MyObject do
|
||||
# not overload
|
||||
class MyRoom(MyObject, Object):
|
||||
"My own expandable room class"
|
||||
pass
|
||||
|
||||
Notes
|
||||
=====
|
||||
|
||||
All above examples puts each class in its own module. This makes it easy
|
||||
to find, but it is really up to you how you organize things. There is
|
||||
nothing stopping you from putting all base classes into one module, for
|
||||
example.
|
||||
|
||||
Also remember that Python may dynamically rename module classes as they
|
||||
are imported. So if you feel it annoying to have to refer to your new
|
||||
default as ``MyObject`` all the time, you can also import them to
|
||||
another name like in the below example:
|
||||
|
||||
::
|
||||
|
||||
from ev import Object as BaseObject
|
||||
from gamesrc.objects.myobject import MyObject as Object
|
||||
class MyRoom(Object, BaseObject):
|
||||
[...]
|
||||
|
||||
This doesn't actually change the meaning of the code, but might make the
|
||||
relationships clearer inside a module.
|
||||
|
|
@ -161,10 +161,17 @@ situations though.
|
|||
What types of data can I save in an Attribute?
|
||||
----------------------------------------------
|
||||
|
||||
If you store a single object (that is, not an iterable list of objects),
|
||||
you can practically store any Python object that can be
|
||||
`pickled <http://docs.python.org/library/pickle.html>`_. Evennia uses
|
||||
the ``pickle`` module to serialize Attribute data into the database.
|
||||
Evennia uses the ``pickle`` module to serialize Attribute data into the
|
||||
database. So if you store a single object (that is, not an iterable list
|
||||
of objects), you can practically store any Python object that can be
|
||||
`pickled <http://docs.python.org/library/pickle.html>`_.
|
||||
|
||||
If you store many objects however, you can only store them using normal
|
||||
Python structures (i.e. in either a *tuple*, *list*, *dictionary* or
|
||||
*set*). All other iterables (such as custom containers) are converted to
|
||||
*lists* by the Attribute (see next section for the reason for this).
|
||||
Since you can nest dictionaries, sets, lists and tuples together in any
|
||||
combination, this is usually not much of a limitation.
|
||||
|
||||
There is one notable type of object that cannot be pickled - and that is
|
||||
a Django database object. These will instead be stored as a wrapper
|
||||
|
|
@ -177,19 +184,12 @@ recursively traverse all iterables to make sure all database objects in
|
|||
them are stored safely. So for efficiency, it can be a good idea to
|
||||
avoid deeply nested lists with objects if you can.
|
||||
|
||||
To store several objects, you may only use python *lists*,
|
||||
*dictionaries* or *tuples* to store them. If you try to save any other
|
||||
form of iterable (like a ``set`` or a home-made class), the Attribute
|
||||
will convert, store and retrieve it as a list instead. Since you can
|
||||
nest dictionaries, lists and tuples together in any combination, this is
|
||||
usually not a limitation you need to worry about.
|
||||
|
||||
*Note that you could fool the safety check if you for example created
|
||||
custom, non-iterable classes and stored database objects in them. So to
|
||||
make this clear - saving such an object is **not supported** and will
|
||||
probably make your game unstable. Store your database objects using
|
||||
lists, tuples, dictionaries or a combination of the three and you should
|
||||
be fine.*
|
||||
lists, tuples, dictionaries, sets or a combination of the four and you
|
||||
should be fine.*
|
||||
|
||||
Examples of valid attribute data:
|
||||
|
||||
|
|
@ -232,13 +232,13 @@ Example of non-supported save:
|
|||
Retrieving Mutable objects
|
||||
--------------------------
|
||||
|
||||
A side effect of the way Evennia stores Attributes is that Python Lists
|
||||
and Dictionaries (only) are handled by custom objects called PackedLists
|
||||
and PackedDicts. These behave just like normal lists and dicts except
|
||||
they have the special property that they save to the database whenever
|
||||
new data gets assigned to them. This allows you to do things like
|
||||
``self.db.mylist[4]`` = val without having to extract the mylist
|
||||
Attribute into a temporary variable first.
|
||||
A side effect of the way Evennia stores Attributes is that Python Lists,
|
||||
Dictionaries and Sets are handled by custom objects called PackedLists,
|
||||
PackedDicts and PackedSets. These behave just like normal lists and
|
||||
dicts except they have the special property that they save to the
|
||||
database whenever new data gets assigned to them. This allows you to do
|
||||
things like ``self.db.mylist[4]`` = val without having to extract the
|
||||
mylist Attribute into a temporary variable first.
|
||||
|
||||
There is however an important thing to remember. If you retrieve this
|
||||
data into another variable, e.g. ``mylist2 = obj.db.mylist``, your new
|
||||
|
|
@ -287,9 +287,92 @@ stop any changes to the structure from updating the database.
|
|||
# iterable is a tuple, so we can edit the internal list as we want
|
||||
# without affecting the database.
|
||||
|
||||
Notes
|
||||
-----
|
||||
Locking and checking Attributes
|
||||
-------------------------------
|
||||
|
||||
Attributes are normally not locked down by default, but you can easily
|
||||
change that for individual Attributes (like those that may be
|
||||
game-sensitive in games with user-level building).
|
||||
|
||||
First you need to set a *lock string* on your Attribute. Lock strings
|
||||
are specified `here <Locks.html>`_. The relevant lock types are
|
||||
|
||||
- *attrread* - limits who may read the value of the Attribute
|
||||
- *attredit* - limits who may set/change this Attribute
|
||||
|
||||
You cannot use e.g. ``obj.db.attrname`` handler to modify Attribute
|
||||
objects (such as setting a lock on them - you will only get the
|
||||
Attribute *value* that way, not the actual Attribute *object*. You get
|
||||
the latter with ``get_attribute_obj`` (see next section) which allows
|
||||
you to set the lock something like this:
|
||||
|
||||
::
|
||||
|
||||
obj.get_attribute_obj.locks.add("attread:all();attredit:perm(Wizards)")
|
||||
|
||||
A lock is no good if nothing checks it -- and by default Evennia does
|
||||
not check locks on Attributes. You have to add a check to your
|
||||
commands/code wherever it fits (such as before setting an Attribute).
|
||||
|
||||
::
|
||||
|
||||
# in some command code where we want to limit
|
||||
# setting of a given attribute name on an object
|
||||
attr = obj.get_attribute_obj(attrname, default=None)
|
||||
if not (attr and attr.locks.check(caller, 'attredit', default=True)):
|
||||
caller.msg("You cannot edit that Attribute!")
|
||||
return
|
||||
# edit the Attribute here
|
||||
|
||||
Note that in this example this lock check will default to ``True`` if no
|
||||
lock was defined on the Attribute (which is the case by default). You
|
||||
can set this to False if you know all your Attributes always check
|
||||
access in all situations. If you want some special control over what the
|
||||
default Attribute access is (such as allowing everyone to view, but
|
||||
never allowing anyone to edit unless explicitly allowing it with a
|
||||
lock), you can use the ``secure_attr`` method on Typeclassed objects
|
||||
like this:
|
||||
|
||||
::
|
||||
|
||||
obj.secure_attr(caller, attrname, value=None,
|
||||
delete=False,
|
||||
default_access_read=True,
|
||||
default_access_edit=False,
|
||||
default_access_create=True)
|
||||
|
||||
The secure\_attr will try to retrieve the attribute value of an existing
|
||||
Attribute if the ``value`` keyword is not set and create/set/delete it
|
||||
otherwise. The *default\_access* keywords specify what should be the
|
||||
default policy for each operation if no appropriate lock string is set
|
||||
on the Attribute.
|
||||
|
||||
Other ways to access Attributes
|
||||
-------------------------------
|
||||
|
||||
Normally ``db`` is all you need. But there there are also several other
|
||||
ways to access information about Attributes, some of which cannot be
|
||||
replicated by ``db``. These are available on all Typeclassed objects:
|
||||
|
||||
- ``has_attribute(attrname)`` - checks if the object has an attribute
|
||||
with the given name. This is equivalent to doing ``obj.db.attrname``.
|
||||
- ``set_attribute(attrname, value)`` - equivalent to
|
||||
``obj.db.attrname = value``.
|
||||
- ``get_attribute(attrname)`` - returns the attribute value. Equivalent
|
||||
to ``obj.db.attrname``.
|
||||
- ``get_attribute_raise(attrname)`` - returns the attribute value, but
|
||||
instead of returning ``None`` if no such attribute is found, this
|
||||
method raises ``AttributeError``.
|
||||
- ``get_attribute_obj(attrname)`` - returns the attribute *object*
|
||||
itself rather than the value stored in it.
|
||||
- ``del_attribute(attrname)`` - equivalent to ``del obj.db.attrname``.
|
||||
Quietly fails if ``attrname`` is not found.
|
||||
- ``del_attribute_raise(attrname)`` - deletes attribute, raising
|
||||
``AttributeError`` if no matching Attribute is found.
|
||||
- ``get_all_attributes`` - equivalent to ``obj.db.all``
|
||||
- ``attr(attrname, value=None, delete=False)`` - this is a convenience
|
||||
function for getting, setting and deleting Attributes. It's
|
||||
recommended to use ``db`` instead.
|
||||
- ``secure_attr(...)`` - lock-checking version of ``attr``. See example
|
||||
in previous section.
|
||||
|
||||
There are several other ways to assign Attributes to be found on the
|
||||
typeclassed objects, all being more 'low-level' underpinnings to
|
||||
``db``/``ndb``. Read their descriptions in the respective modules.
|
||||
|
|
|
|||
169
docs/sphinx/source/wiki/Caches.rst
Normal file
169
docs/sphinx/source/wiki/Caches.rst
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
Caches
|
||||
======
|
||||
|
||||
*Note: This is an advanced topic. You might want to skip it on a first
|
||||
read-through.*
|
||||
|
||||
Evennia is a fully persistent system, which means that it will store
|
||||
things in the database whenever its state changes. Since accessing the
|
||||
database i comparably expensive, Evennia uses an extensive *caching*
|
||||
scheme. Caching normally means that once data is read from the database,
|
||||
it is stored in memory for quick retrieval henceforth. Only when data
|
||||
changes will the database be accessed again (and the cache updated).
|
||||
|
||||
With a few exceptions, caching are primarily motivated by speed and to
|
||||
minimize bottlenecks found by profiling the server. Some systems must
|
||||
access certain pieces of data often, and going through the django API
|
||||
over and over builds up. Depending on operation, individual speedups of
|
||||
hundreds of times can be achieved by clever caching.
|
||||
|
||||
The price for extended caching is memory consumption and added
|
||||
complexity. This page tries to explain the various cache strategies in
|
||||
place. Most users should not have to worry about them, but if you ever
|
||||
try to "bang the metal" with Evennia, you should know what you are
|
||||
seeing.
|
||||
|
||||
The default ``@server`` command will give a brief listing of the memory
|
||||
usage of most relevant caches.
|
||||
|
||||
Idmapper
|
||||
--------
|
||||
|
||||
Evennia's django object model is extended by *idmapper* functionality.
|
||||
The idmapper is an external third-party system that sits in
|
||||
``src/utils/idmapper``. The idmapper is an on-demand memory mapper for
|
||||
all database models in the game. This means that a given database object
|
||||
is represented by the same memory area whenever it is accessed. This may
|
||||
sound trivial but it is not - in plain Django there is no such
|
||||
guarantee. Doing something like ``objdb.test = "Test"`` (were objdb is a
|
||||
django model instance) would be unsafe and most likely the ``test``
|
||||
variable would be lost next time the model is retrieved from the
|
||||
database. As Evennia ties `Typeclasses <Typeclasses.html>`_ to django
|
||||
models, this would be a catastophy.
|
||||
|
||||
Idmapper is originally a memory saver for django websites. In the case
|
||||
of a website, object access is brief and fleeting - not so for us. So we
|
||||
have extended idmapper to never loose its reference to a stored object
|
||||
(not doing this was the cause of a very long-standing, very hard-to-find
|
||||
bug).
|
||||
|
||||
Idmapper is an on-demand cache, meaning that it will only cache objects
|
||||
that are actually accessed. Whereas it is possible to clean the idmapper
|
||||
cache via on-model methods, this does not necessarily mean its memory
|
||||
will be freed - this depends on any lingering references in the system
|
||||
(this is how Python's reference counting works). If you ever need to
|
||||
clean the idmapper cache, the safest way is therefore a soft-reload of
|
||||
the server (via e.g. the ``@reload`` command).
|
||||
|
||||
Most developers will not need to care with the idmapper cache - it just
|
||||
makes models work intuitively. It is visible mostly in that all database
|
||||
models in Evennia inherits from
|
||||
``src.utils.idmapper.models.SharedMemoryModel``.
|
||||
|
||||
On-object variable cache
|
||||
------------------------
|
||||
|
||||
All database fields on all objects in Evennia are cached by use of
|
||||
`Python
|
||||
properties <http://docs.python.org/library/functions.html#property>`_.
|
||||
So when you do ``name = obj.key``, you are actually *not* directly
|
||||
accessing a database field "key" on the object. What you are doing is
|
||||
actually to access a handler. This handler looks for hidden variable
|
||||
named ``_cached_db_key``. If that can be found, it is what is returned.
|
||||
If not, the actual database field, named ``db_key`` are accessed. The
|
||||
result is returned and cached for next time.
|
||||
|
||||
The naming scheme is consistent, so a given property ``obj.foo`` is a
|
||||
handler with a cache named ``obj._cached_db_foo`` and a database field
|
||||
``obj.db_key.`` The handler methods for the property are always named
|
||||
``obj.foo_get()``, ``obj.foo_set()`` and ``obj.foo_del()`` (all are not
|
||||
always needed).
|
||||
|
||||
Apart from caching, property handlers also serves another function -
|
||||
they hide away Django administration. So doing ``obj.key = "Peter"``
|
||||
will not only assign (and cache) the string "Peter" in the database
|
||||
field ``obj.db_key``, it will also call ``obj.save()`` for you in order
|
||||
to update the database.
|
||||
|
||||
Hiding away the model fields presents one complication for developers,
|
||||
and that is searching using normal django methods. Basically, if you
|
||||
search using e.g. the standard django ``filter`` method, you must search
|
||||
for ``db_key``, not ``key``. Only the former is known by django, the
|
||||
latter will give an invalid-field error. If you use Evennia's own search
|
||||
methods you don't need to worry about this, they look for the right
|
||||
things behind the scenes for you.
|
||||
|
||||
Mutable variable caches
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Some object properties may appear mutable - that is, they return lists.
|
||||
One such example is the ``permissions`` property. This is however not
|
||||
actually a list - it's just a handler that *returns* and *accepts*
|
||||
lists. ``db_permissions`` is actually stored as a comma-separated
|
||||
string. The uptake of this is that you cannot do list operations on the
|
||||
handler. So ``obj.permissions.append('Immortals')`` will not work.
|
||||
Rather, you will have to do such operations on what is returned. Like
|
||||
this:
|
||||
|
||||
::
|
||||
|
||||
perms = obj.permissions # this returns a list!
|
||||
perms.append("Immortals")
|
||||
obj.permissions = perms # overwrites with new list
|
||||
|
||||
Content cache
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
A special case of on-object caching is the *content* cache. Finding the
|
||||
"contents" of a particular location turns out to be a very common and
|
||||
pretty expensive operation. Whenever a person moves, says something or
|
||||
does other things, "everyone else" in a given location must be informed.
|
||||
This means a database search for which objects share the location.
|
||||
|
||||
``obj.contents`` is a convenient container that at every moment contains
|
||||
a cached list of all objects "inside" that particular object. It is
|
||||
updated by the ``location`` property. So ``obj1.location = obj2`` will
|
||||
update ``obj2.contents`` on the fly to contain ``obj1``. It will also
|
||||
remove ``obj1`` from the ``contents`` list of its previous location.
|
||||
Testing shows that when moving from one room to another, finding and
|
||||
messaging everyone in the room took up as much as *25%* of the total
|
||||
computer time needed for the operation. After caching ``contents``,
|
||||
messaging now takes up *0.25%* instead ...
|
||||
|
||||
The contents cache should be used at all times. The main thing to
|
||||
remember is that if you were to somehow bypass the ``location`` handler
|
||||
(such as by setting the ``db_location`` field manually), you will bring
|
||||
the cache and database out of sync until you reload the server.
|
||||
|
||||
Typeclass cache
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
All typeclasses are cached on the database model. This allows for quick
|
||||
access to the typeclass through ``dbobj.typeclass``. Behind the scenes
|
||||
this operation will import the typeclass definition from a path stored
|
||||
in ``db_typeclass_path`` (available via the property handler
|
||||
``typeclass_path``). All checks and eventual debug messages will be
|
||||
handled, and the result cached.
|
||||
|
||||
The only exception to the caching is if the typeclass module had some
|
||||
sort of syntax error or other show-stopping bug. The default typeclass
|
||||
(as defined in ``settings``) will then be loaded instead. The error will
|
||||
be reported and *no* caching will take place. This is in order to keep
|
||||
reloading the typeclass also next try, until it is fixed.
|
||||
|
||||
On-object Attribute cache
|
||||
-------------------------
|
||||
|
||||
`Attribute <Attributes.html>`_ lookups are cached by use of hidden
|
||||
dictionaries on all `Typeclassed <Typeclasses.html>`_ objects - this
|
||||
removes the necessity for subsequent database look-ups in order to
|
||||
retrieve attributes. Both ``db`` and ``ndn`` work the same way in this
|
||||
regard.
|
||||
|
||||
Attribute value cache
|
||||
---------------------
|
||||
|
||||
Each Attribute object also caches the values stored in it. Whenever
|
||||
retrieving an attribute value, it is also cached for future accesses. In
|
||||
effect this means that (after the first time) accessing an attribute is
|
||||
equivalent to accessing any normal property.
|
||||
|
|
@ -27,7 +27,7 @@ defined on.
|
|||
DefaultCmdset and available in the game.
|
||||
|
||||
The full set of available commands (all three sub-sets above) currently
|
||||
contains 85 commands in 6 categories. More information about how
|
||||
contains 86 commands in 6 categories. More information about how
|
||||
commands work can be found in the `Command <Commands.html>`_
|
||||
documentation.
|
||||
|
||||
|
|
@ -666,7 +666,7 @@ module <https://code.google.com/p/evennia/source/browse/src/commands/default/bui
|
|||
~~~~~
|
||||
|
||||
- ``key`` = ``@home``
|
||||
- ``aliases`` = ``<None>``
|
||||
- ``aliases`` = ``@sethome``
|
||||
- `locks <Locks.html>`_ = ``cmd:perm(@home) or perm(Builders)``
|
||||
- `help\_category <HelpSystem.html>`_ = ``Building``
|
||||
- [`HelpSystem <HelpSystem.html>`_\ #Auto-help\_system Auto-help]
|
||||
|
|
@ -910,19 +910,29 @@ module <https://code.google.com/p/evennia/source/browse/src/commands/default/bui
|
|||
|
||||
::
|
||||
|
||||
teleport
|
||||
teleport object to another location
|
||||
|
||||
Usage:
|
||||
@tel/switch [<object> =] <location>
|
||||
@tel/switch [<object> =] <target location>
|
||||
|
||||
Examples:
|
||||
@tel Limbo
|
||||
@tel/quiet box Limbo
|
||||
@tel/tonone box
|
||||
|
||||
Switches:
|
||||
quiet - don't echo leave/arrive messages to the source/target
|
||||
locations for the move.
|
||||
intoexit - if target is an exit, teleport INTO
|
||||
the exit object instead of to its destination
|
||||
tonone - if set, teleport the object to a None-location. If this
|
||||
switch is set, <target location> is ignored.
|
||||
Note that the only way to retrieve
|
||||
an object from a None location is by direct #dbref
|
||||
reference.
|
||||
|
||||
Teleports an object or yourself somewhere.
|
||||
|
||||
Teleports an object somewhere. If no object is given, you yourself
|
||||
is teleported to the target location.
|
||||
|
||||
@tunnel
|
||||
~~~~~~~
|
||||
|
|
@ -1487,6 +1497,29 @@ General
|
|||
`Link to Python
|
||||
module <https://code.google.com/p/evennia/source/browse/src/commands/default/general.py>`_
|
||||
|
||||
@color
|
||||
~~~~~~
|
||||
|
||||
- ``key`` = ``@color``
|
||||
- ``aliases`` = ``<None>``
|
||||
- `locks <Locks.html>`_ = ``cmd:all()``
|
||||
- `help\_category <HelpSystem.html>`_ = ``General``
|
||||
- [`HelpSystem <HelpSystem.html>`_\ #Auto-help\_system Auto-help]
|
||||
(``__doc__ string``) =
|
||||
|
||||
::
|
||||
|
||||
testing colors
|
||||
|
||||
Usage:
|
||||
@color ansi|xterm256
|
||||
|
||||
Print a color map along with in-mud color codes, while testing what is supported in your client.
|
||||
Choices are 16-color ansi (supported in most muds) or the 256-color xterm256 standard.
|
||||
No checking is done to determine your client supports color - if not you will
|
||||
see rubbish appear.
|
||||
|
||||
|
||||
@encoding (OOC command)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
|||
|
|
@ -1,47 +1,33 @@
|
|||
Evennia Licence FAQ
|
||||
===================
|
||||
|
||||
Evennia is licensed under the very friendly *Modified Clarified Artistic
|
||||
License*. You can find the license as ``LICENCE`` in the Evennia root
|
||||
directory. You can also read the full license file
|
||||
Evennia is licensed under the very friendly BSD License. You can find
|
||||
the license as ``LICENCE.txt`` in the Evennia root directory. You can
|
||||
also read the full license file
|
||||
`here <http://code.google.com/p/evennia/source/browse/LICENSE.txt>`_.
|
||||
|
||||
You should read the full license text to know what it says exactly, but
|
||||
here are some answers to common questions.
|
||||
|
||||
Q: When creating a game using Evennia, what does the licence permit me to do with it?
|
||||
-------------------------------------------------------------------------------------
|
||||
|
||||
**A:** It's your own game world to do with as you please! To summarize,
|
||||
a MUD world you create using Evennia (i.e. the files you create in
|
||||
``/game/``) falls under **§6** of the license (it's a sort of
|
||||
"library"). So your game world and all its contents belongs to you (as
|
||||
it should be). Keep it to yourself or re-distribute it under any license
|
||||
of your choice - or sell it and become filthy rich for all we care.
|
||||
**A:** It's your own game world to do with as you please! Keep it to
|
||||
yourself or re-distribute it under any license of your choice - or sell
|
||||
it and become filthy rich for all we care.
|
||||
|
||||
Q: I have modified Evennia itself, what does the license say about that?
|
||||
------------------------------------------------------------------------
|
||||
|
||||
**A:** The Evennia package itself (i.e. the stuff you download from us)
|
||||
is referred to as "The Package, Standard version" in the license.
|
||||
**A:** The License allows you to do whatever you want with your modified
|
||||
Evennia, including re-distributing or selling it, as long as you include
|
||||
our license and copyright info in the ``LICENSE.txt`` file along with
|
||||
your distribution.
|
||||
|
||||
- If you just fixed a typo or bug, that falls under **§2** - that is,
|
||||
you don't *have* to do anything to appease the license. Regardless,
|
||||
we'd of course appreciate it if you submitted bugs/fixes to us so
|
||||
Evennia becomes more complete!.
|
||||
- If you made bigger modifications or added new features to the server,
|
||||
that's also ok, but falls under **§3** - you must make a clear note
|
||||
of the changes you did and put those changes into public domain
|
||||
(since it's then no longer a "Standard version"). You could also
|
||||
contact the Evennia developers to make separate arrangements ... but
|
||||
of course, if you plan to add new features to the server, the easiest
|
||||
way to do so is to simply become an Evennia developer!
|
||||
... Of course, if you add bug fixes or add some new snazzy features we
|
||||
still *softly nudge* you to make those changes available upstream so
|
||||
they could be added to the core Evennia package. The license don't
|
||||
require you to do it, but that doesn't mean we can't still greatly
|
||||
appreciate it if you do!
|
||||
|
||||
Q: Can I re-distribute the Evennia server package along with my custom game implementation?
|
||||
-------------------------------------------------------------------------------------------
|
||||
|
||||
**A:** Sure. This is covered in **§4** - just package the "Standard
|
||||
version" (that is, the one you download from us) with your game files.
|
||||
Also make sure to include the original license and disclaimers and note
|
||||
where users may get "plain" Evennia should they want to download it of
|
||||
their own.
|
||||
**A:** Sure. As long as the text in LICENSE.txt is included.
|
||||
|
|
|
|||
|
|
@ -34,6 +34,10 @@ Third-party Evennia links
|
|||
|
||||
- `Avaloria <http://code.google.com/p/avaloria/>`_ (MUD under
|
||||
development, using Evennia)
|
||||
- `Winter's Oasis <http://blog.wintersoasis.com/>`_ (MUCK under
|
||||
development, using Evennia)
|
||||
- `Latitude <https://github.com/dbenoy/latitude>`_ (MUCK under
|
||||
development, using Evennia)
|
||||
|
||||
General mud/game development ideas and discussions
|
||||
--------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ Central <DeveloperCentral.html>`_.
|
|||
|
||||
- `Tutorial: Adding a new default
|
||||
command <AddingCommandTutorial.html>`_
|
||||
- `Tutorial: Adding new Object typeclasses and
|
||||
defaults <AddingObjectTypeclassTutorial.html>`_
|
||||
|
||||
Implementation ideas
|
||||
--------------------
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue