mirror of
https://github.com/evennia/evennia.git
synced 2026-04-06 07:57:16 +02:00
Updated HTML docs
This commit is contained in:
parent
485838ffe2
commit
effa0f90f0
128 changed files with 8699 additions and 4764 deletions
|
|
@ -1,3 +1,379 @@
|
|||
# Channels
|
||||
# Channels
|
||||
|
||||
In a multiplayer game, players often need other means of in-game communication
|
||||
than moving to the same room and use `say` or `emote`.
|
||||
|
||||
_Channels_ allows Evennia's to act as a fancy chat program. When a player is
|
||||
connected to a channel, sending a message to it will automatically distribute
|
||||
it to every other subscriber.
|
||||
|
||||
Channels can be used both for chats between [Accounts](./Accounts) and between
|
||||
[Objects](./Objects) (usually Characters). Chats could be both OOC
|
||||
(out-of-character) or IC (in-charcter) in nature. Some examples:
|
||||
|
||||
- A support channel for contacting staff (OOC)
|
||||
- A general chat for discussing anything and foster community (OOC)
|
||||
- Admin channel for private staff discussions (OOC)
|
||||
- Private guild channels for planning and organization (IC/OOC depending on game)
|
||||
- Cyberpunk-style retro chat rooms (IC)
|
||||
- In-game radio channels (IC)
|
||||
- Group telephathy (IC)
|
||||
- Walkie talkies (IC)
|
||||
|
||||
```versionchanged:: 1.0
|
||||
|
||||
Channel system changed to use a central 'channel' command and nicks instead of
|
||||
auto-generated channel-commands and -cmdset. ChannelHandler was removed.
|
||||
|
||||
```
|
||||
|
||||
## Using channels in-game
|
||||
|
||||
In the default command set, channels are all handled via the mighty
|
||||
[channel command](api:evennia.commands.default.comms.CmdChannel), `channel` (or
|
||||
`chan`). By default, this command will assume all entities dealing with
|
||||
channels are `Accounts`.
|
||||
|
||||
### Viewing and joining channels
|
||||
|
||||
channel - shows your subscriptions
|
||||
channel/all - shows all subs available to you
|
||||
channel/who - shows who subscribes to this channel
|
||||
|
||||
To join/unsub a channel do
|
||||
|
||||
channel/sub channelname
|
||||
channel/unsub channelname
|
||||
|
||||
If you temporarily don't want to hear the channel for a while (without actually
|
||||
unsubscribing), you can mute it:
|
||||
|
||||
channel/mute channelname
|
||||
channel/unmute channelname
|
||||
|
||||
### Chat on channels
|
||||
|
||||
To speak on a channel, do
|
||||
|
||||
channel public Hello world!
|
||||
|
||||
If the channel-name has spaces in it, you need to use a '`=`':
|
||||
|
||||
channel rest room = Hello world!
|
||||
|
||||
Now, this is more to type than we'd like, so when you join a channel, the
|
||||
system automatically sets up an personal alias so you can do this instead:
|
||||
|
||||
public Hello world
|
||||
|
||||
```warning::
|
||||
|
||||
This shortcut will not work if the channel-name has spaces in it.
|
||||
So channels with long names should make sure to provide a one-word alias as
|
||||
well.
|
||||
```
|
||||
|
||||
Any user can make up their own channel aliases:
|
||||
|
||||
channel/alias public = foo;bar
|
||||
|
||||
You can now just do
|
||||
|
||||
foo Hello world!
|
||||
bar Hello again!
|
||||
|
||||
And even remove the default one if they don't want to use it
|
||||
|
||||
channel/unalias public
|
||||
public Hello
|
||||
|
||||
But you can also use your alias with the `channel` command:
|
||||
|
||||
channel foo Hello world!
|
||||
|
||||
> What happens when aliasing is that a [nick](./Nicks) is created that maps your
|
||||
> alias + argument onto calling the `channel` command. So when you enter `foo hello`,
|
||||
> what the server sees is actually `channel foo = hello`. The system is also
|
||||
> clever enough to know that whenever you search for channels, your channel-nicks
|
||||
> should also be considered so as to convert your input to an existing channel name.
|
||||
|
||||
You can check if you missed channel conversations by viewing the channel's
|
||||
scrollback with
|
||||
|
||||
channel/history public
|
||||
|
||||
This retrieves the last 20 lines of text (also from a time when you were
|
||||
offline). You can step further back by specifying how many lines back to start:
|
||||
|
||||
channel/history public = 30
|
||||
|
||||
This again retrieve 20 lines, but starting 30 lines back (so you'll get lines
|
||||
30-50 counting backwards).
|
||||
|
||||
|
||||
### Channel administration
|
||||
|
||||
To create/destroy a new channel you can do
|
||||
|
||||
channel/create channelname;alias;alias = description
|
||||
channel/destroy channelname
|
||||
|
||||
Aliases are optional but can be good for obvious shortcuts everyone may want to
|
||||
use. The description is used in channel-listings. You will automatically join a
|
||||
channel you created and will be controlling it. You can also use `channel/desc` to
|
||||
change the description on a channel you wnn later.
|
||||
|
||||
If you control a channel you can also kick people off it:
|
||||
|
||||
channel/boot mychannel = annoyinguser123 : stop spamming!
|
||||
|
||||
The last part is an optional reason to send to the user before they are booted.
|
||||
You can give a comma-separated list of channels to kick the same user from all
|
||||
those channels at once. The user will be unsubbed from the channel and all
|
||||
their aliases will be wiped. But they can still rejoin if they like.
|
||||
|
||||
channel/ban mychannel = annoyinguser123
|
||||
channel/ban - view bans
|
||||
channel/unban mychannel = annoyinguser123
|
||||
|
||||
Banning adds the user to the channels blacklist. This means they will not be
|
||||
able to _rejoin_ if you boot them. You will need to run `channel/boot` to
|
||||
actually kick them out.
|
||||
|
||||
See the [Channel command](api:evennia.commands.default.comms.CmdChannel) api
|
||||
docs (and in-game help) for more details.
|
||||
|
||||
Admin-level users can also modify channel's [locks](./Locks):
|
||||
|
||||
channel/lock buildchannel = listen:all();send:perm(Builders)
|
||||
|
||||
Channels use three lock-types by default:
|
||||
|
||||
- `listen` - who may listen to the channel. Users without this access will not
|
||||
even be able to join the channel and it will not appear in listings for them.
|
||||
- `send` - who may send to the channel.
|
||||
- `control` - this is assigned to you automatically when you create the channel. With
|
||||
control over the channel you can edit it, boot users and do other management tasks.
|
||||
|
||||
|
||||
#### Restricting channel administration
|
||||
|
||||
By default everyone can use the channel command ([evennia.commands.default.comms.CmdChannel](api:evennia.commands.default.comms.CmdChannel))
|
||||
to create channels and will then control the channels they created (to boot/ban
|
||||
people etc). If you as a developer does not want regular players to do this
|
||||
(perhaps you want only staff to be able to spawn new channels), you can
|
||||
override the `channel` command and change its `locks` property.
|
||||
|
||||
The default `help` command has the following `locks` property:
|
||||
|
||||
```python
|
||||
locks = "cmd:not perm(channel_banned); admin:all(); manage:all(); changelocks: perm(Admin)"
|
||||
```
|
||||
|
||||
This is a regular [lockstring](./Locks).
|
||||
|
||||
- `cmd: pperm(channel_banned)` - The `cmd` locktype is the standard one used for all Commands.
|
||||
an accessing object failing this will not even know that the command exists. The `pperm()` lockfunc
|
||||
checks an on-account [Permission](Building Permissions) 'channel_banned' - and the `not` means
|
||||
that if they _have_ that 'permission' they are cut off from using the `channel` command. You usually
|
||||
don't need to change this lock.
|
||||
- `admin:all()` - this is a lock checked in the `channel` command itself. It controls access to the
|
||||
`/boot`, `/ban` and `/unban` switches (by default letting everyone use them).
|
||||
- `manage:all()` - this controls access to the `/create`, `/destroy`, `/desc` switches.
|
||||
- `changelocks: perm(Admin)` - this controls access to the `/lock` and `/unlock` switches. By
|
||||
default this is something only [Admins](Building Permissions) can change.
|
||||
|
||||
> Note - while `admin:all()` and `manage:all()` will let everyone use these switches, users
|
||||
> will still only be able to admin or destroy channels they actually control!
|
||||
|
||||
If you only want (say) Builders and higher to be able to create and admin
|
||||
channels you could override the `help` command and change the lockstring to:
|
||||
|
||||
```python
|
||||
# in for example mygame/commands/commands.py
|
||||
|
||||
from evennia import default_cmds
|
||||
|
||||
class MyCustomChannelCmd(default_cmds.CmdChannel):
|
||||
locks = "cmd: not pperm(channel_banned);admin:perm(Builder);manage:perm(Builder);changelocks:perm(Admin)"
|
||||
|
||||
```
|
||||
|
||||
Add this custom command to your default cmdset and regular users wil now get an
|
||||
access-denied error when trying to use use these switches.
|
||||
|
||||
## Allowing Characters to use Channels
|
||||
|
||||
The default `channel` command ([evennia.commands.default.comms.CmdChannel](api:evennia.commands.default.comms.CmdChannel))
|
||||
sits in the `Account` [command set](./Command-Sets). It is set up such that it will
|
||||
always operate on `Accounts`, even if you were to add it to the
|
||||
`CharacterCmdSet`.
|
||||
|
||||
It's a one-line change to make this command accept non-account callers. But for
|
||||
convenience we provide a version for Characters/Objects. Just import
|
||||
[evennia.commands.default.comms.CmdObjectChannel](api:evennia.commands.default.comms.CmdObjectChannel)
|
||||
and inherit from that instead.
|
||||
|
||||
## Customizing channel output and behavior
|
||||
|
||||
When distributing a message, the channel will call a series of hooks on itself
|
||||
and (more importantly) on each recipient. So you can customize things a lot by
|
||||
just modifying hooks on your normal Object/Account typeclasses.
|
||||
|
||||
Internally, the message is sent with
|
||||
`channel.msg(message, senders=sender, bypass_mute=False, **kwargs)`, where
|
||||
`bypass_mute=True` means the message ignores muting (good for alerts or if you
|
||||
delete the channel etc) and `**kwargs` are any extra info you may want to pass
|
||||
to the hooks. The `senders` (it's always only one in the default implementation
|
||||
but could in principle be multiple) and `bypass_mute` are part of the `kwargs`
|
||||
below:
|
||||
|
||||
1. `channel.at_pre_msg(message, **kwargs)`
|
||||
2. For each recipient:
|
||||
- `message = recipient.at_pre_channel_msg(message, channel, **kwargs)` -
|
||||
allows for the message to be tweaked per-receiver (for example coloring it depending
|
||||
on the users' preferences). If this method returns `False/None`, that
|
||||
recipient is skipped.
|
||||
- `recipient.channel_msg(message, channel, **kwargs)` - actually sends to recipient.
|
||||
- `recipient.at_post_channel_msg(message, channel, **kwargs)` - any post-receive effects.
|
||||
3. `channel.at_post_channel_msg(message, **kwargs)`
|
||||
|
||||
Note that `Accounts` and `Objects` both have their have separate sets of hooks.
|
||||
So make sure you modify the set actually used by your subcribers (or both).
|
||||
Default channels all use `Account` subscribers.
|
||||
|
||||
## Channels in code
|
||||
|
||||
For most common changes, the default channel, the recipient hooks and possibly
|
||||
overriding the `channel` command will get you very far. But you can also tweak
|
||||
channels themselves.
|
||||
|
||||
Channels are [Typeclassed](./Typeclasses) entities. This means they are
|
||||
persistent in the database, can have [attributes](./Attributes) and [Tags](./Tags)
|
||||
and can be easily extended.
|
||||
|
||||
To change which channel typeclass Evennia uses for default commands, change
|
||||
`settings.BASE_CHANNEL_TYPECLASS`. The base command class is
|
||||
[`evennia.comms.comms.DefaultChannel`](api:evennia.comms.comms.DefaultChannel).
|
||||
There is an empty child class in `mygame/typeclasses/channels.py`, same
|
||||
as for other typelass-bases.
|
||||
|
||||
In code you create a new channel with `evennia.create_channel` or
|
||||
`Channel.create`:
|
||||
|
||||
```python
|
||||
from evennia import create_channel, search_object
|
||||
from typeclasses.channels import Channel
|
||||
|
||||
channel = create_channel("my channel", aliases=["mychan"], locks=..., typeclass=...)
|
||||
# alternative
|
||||
channel = Channel.create("my channel", aliases=["mychan"], locks=...)
|
||||
|
||||
# connect to it
|
||||
me = search_object(key="Foo")[0]
|
||||
channel.connect(me)
|
||||
|
||||
# send to it (this will trigger the channel_msg hooks described earlier)
|
||||
channel.msg("Hello world!", senders=me)
|
||||
|
||||
# view subscriptions (the SubscriptionHandler handles all subs under the hood)
|
||||
channel.subscriptions.has(me) # check we subbed
|
||||
channel.subscriptions.all() # get all subs
|
||||
channel.subscriptions.online() # get only subs currently online
|
||||
channel.subscriptions.clear() # unsub all
|
||||
|
||||
# leave channel
|
||||
channel.disconnect(me)
|
||||
|
||||
# permanently delete channel (will unsub everyone)
|
||||
channel.delete()
|
||||
|
||||
```
|
||||
|
||||
The Channel's `.connect` method will accept both `Account` and `Object` subscribers
|
||||
and will handle them transparently.
|
||||
|
||||
The channel has many more hooks, both hooks shared with all typeclasses as well
|
||||
as special ones related to muting/banning etc. See the channel class for
|
||||
details.
|
||||
|
||||
## Channel logging
|
||||
|
||||
```versionchanged:: 0.7
|
||||
|
||||
Channels changed from using Msg to TmpMsg and optional log files.
|
||||
```
|
||||
```versionchanged:: 1.0
|
||||
|
||||
Channels stopped supporting Msg and TmpMsg, using only log files.
|
||||
```
|
||||
|
||||
The channel messages are not stored in the database. A channel is instead
|
||||
always logged to a regular text log-file
|
||||
`mygame/server/logs/channel_<channelname>.log`. This is where `channels/history channelname`
|
||||
gets its data from. A channel's log will rotate when it grows too big, which
|
||||
thus also automatically limits the max amount of history a user can view with
|
||||
`/history`.
|
||||
|
||||
The log file name is set on the channel class as the `log_file` property. This
|
||||
is a string that takes the formatting token `{channelname}` to be replaced with
|
||||
the (lower-case) name of the channel. By default the log is written to in the
|
||||
channel's `at_post_channel_msg` method.
|
||||
|
||||
|
||||
### Properties on Channels
|
||||
|
||||
Channels have all the standard properties of a Typeclassed entity (`key`,
|
||||
`aliases`, `attributes`, `tags`, `locks` etc). This is not an exhaustive list;
|
||||
see the [Channel api docs](api:evennia.comms.comms.DefaultChannel) for details.
|
||||
|
||||
- `send_to_online_only` - this class boolean defaults to `True` and is a
|
||||
sensible optimization since people offline people will not see the message anyway.
|
||||
- `log_file` - this is a string that determines the name of the channel log file. Default
|
||||
is `"channel_{channelname}.log"`. The log file will appear in `settings.LOG_DIR` (usually
|
||||
`mygame/server/logs/`). You should usually not change this.
|
||||
- `channel_prefix_string` - this property is a string to easily change how
|
||||
the channel is prefixed. It takes the `channelname` format key. Default is `"[{channelname}] "`
|
||||
and produces output like `[public] ...``.
|
||||
- `subscriptions` - this is the [SubscriptionHandler](api:evennia.comms.comms#SubscriptionHandler), which
|
||||
has methods `has`, `add`, `remove`, `all`, `clear` and also `online` (to get
|
||||
only actually online channel-members).
|
||||
- `wholist`, `mutelist`, `banlist` are properties that return a list of subscribers,
|
||||
as well as who are currently muted or banned.
|
||||
- `channel_msg_nick_pattern` - this is a regex pattern for performing the in-place nick
|
||||
replacement (detect that `channelalias <msg` means that you want to send a message to a channel).
|
||||
This pattern accepts an `{alias}` formatting marker. Don't mess with this unless you really
|
||||
want to change how channels work.
|
||||
- `channel_msg_nick_replacement` - this is a string on the [nick replacement
|
||||
- form](Nicks). It accepts the `{channelname}` formatting tag. This is strongly tied to the
|
||||
`channel` command and is by default `channel {channelname} = $1`.
|
||||
|
||||
Notable `Channel` hooks:
|
||||
|
||||
- `at_pre_channel_msg(message, **kwargs)` - called before sending a message, to
|
||||
modify it. Not used by default.
|
||||
- `msg(message, senders=..., bypass_mute=False, **kwargs)` - send the message onto
|
||||
the channel. The `**kwargs` are passed on into the other call hooks (also on the recipient).
|
||||
- `at_post_channel_msg(message, **kwargs)` - by default this is used to store the message
|
||||
to the log file.
|
||||
- `channel_prefix(message)` - this is called to allow the channel to prefix. This is called
|
||||
by the object/account when they build the message, so if wanting something else one can
|
||||
also just remove that call.
|
||||
- every channel message. By default it just returns `channel_prefix_string`.
|
||||
- `has_connection(subscriber)` - shortcut to check if an entity subscribes to
|
||||
this channel.
|
||||
- `mute/unmute(subscriber)` - this mutes the channel for this user.
|
||||
- `ban/unban(subscriber)` - adds/remove user from banlist.
|
||||
- `connect/disconnect(subscriber)` - adds/removes a subscriber.
|
||||
- `add_user_channel_alias(user, alias, **kwargs)` - sets up a user-nick for this channel. This is
|
||||
what maps e.g. `alias <msg>` to `channel channelname = <msg>`.
|
||||
- `remove_user_channel_alias(user, alias, **kwargs)` - remove an alias. Note that this is
|
||||
a class-method that will happily remove found channel-aliases from the user linked to _any_
|
||||
channel, not only from the channel the method is called on.
|
||||
- `pre_join_channel(subscriber)` - if this returns `False`, connection will be refused.
|
||||
- `post_join_channel(subscriber)` - by default this sets up a users's channel-nicks/aliases.
|
||||
- `pre_leave_channel(subscriber)` - if this returns `False`, the user is not allowed to leave.
|
||||
- `post_leave_channel(subscriber)` - this will clean up any channel aliases/nicks of the user.
|
||||
- `delete` the standard typeclass-delete mechanism will also automatically un-subscribe all
|
||||
subscribers (and thus wipe all their aliases).
|
||||
|
||||
TODO: Channels are covered in [Communications](./Communications) right now.
|
||||
|
|
@ -1,113 +1,8 @@
|
|||
# Communications
|
||||
|
||||
TODO: Remove this page?
|
||||
|
||||
Apart from moving around in the game world and talking, players might need other forms of
|
||||
communication. This is offered by Evennia's `Comm` system. Stock evennia implements a 'MUX-like'
|
||||
system of channels, but there is nothing stopping you from changing things to better suit your
|
||||
taste.
|
||||
|
||||
Comms rely on two main database objects - `Msg` and `Channel`. There is also the `TempMsg` which
|
||||
mimics the API of a `Msg` but has no connection to the database.
|
||||
|
||||
## Msg
|
||||
|
||||
The `Msg` object is the basic unit of communication in Evennia. A message works a little like an
|
||||
e-mail; it always has a sender (a [Account](./Accounts)) and one or more recipients. The recipients
|
||||
may be either other Accounts, or a *Channel* (see below). You can mix recipients to send the message
|
||||
to both Channels and Accounts if you like.
|
||||
|
||||
Once created, a `Msg` is normally not changed. It is peristently saved in the database. This allows
|
||||
for comprehensive logging of communications. This could be useful for allowing senders/receivers to
|
||||
have 'mailboxes' with the messages they want to keep.
|
||||
|
||||
### Properties defined on `Msg`
|
||||
|
||||
- `senders` - this is a reference to one or many [Account](./Accounts) or [Objects](./Objects) (normally
|
||||
*Characters*) sending the message. This could also be an *External Connection* such as a message
|
||||
coming in over IRC/IMC2 (see below). There is usually only one sender, but the types can also be
|
||||
mixed in any combination.
|
||||
- `receivers` - a list of target [Accounts](./Accounts), [Objects](./Objects) (usually *Characters*) or
|
||||
*Channels* to send the message to. The types of receivers can be mixed in any combination.
|
||||
- `header` - this is a text field for storing a title or header for the message.
|
||||
- `message` - the actual text being sent.
|
||||
- `date_sent` - when message was sent (auto-created).
|
||||
- `locks` - a [lock definition](./Locks).
|
||||
- `hide_from` - this can optionally hold a list of objects, accounts or channels to hide this `Msg`
|
||||
from. This relationship is stored in the database primarily for optimization reasons, allowing for
|
||||
quickly post-filter out messages not intended for a given target. There is no in-game methods for
|
||||
setting this, it's intended to be done in code.
|
||||
|
||||
You create new messages in code using `evennia.create_message` (or
|
||||
`evennia.utils.create.create_message.`)
|
||||
|
||||
## TempMsg
|
||||
|
||||
`evennia.comms.models` also has `TempMsg` which mimics the API of `Msg` but is not connected to the
|
||||
database. TempMsgs are used by Evennia for channel messages by default. They can be used for any
|
||||
system expecting a `Msg` but when you don't actually want to save anything.
|
||||
|
||||
## Channels
|
||||
|
||||
Channels are [Typeclassed](./Typeclasses) entities, which mean they can be easily extended and their
|
||||
functionality modified. To change which channel typeclass Evennia uses, change
|
||||
settings.BASE_CHANNEL_TYPECLASS.
|
||||
|
||||
Channels act as generic distributors of messages. Think of them as "switch boards" redistributing
|
||||
`Msg` or `TempMsg` objects. Internally they hold a list of "listening" objects and any `Msg` (or
|
||||
`TempMsg`) sent to the channel will be distributed out to all channel listeners. Channels have
|
||||
[Locks](./Locks) to limit who may listen and/or send messages through them.
|
||||
|
||||
The *sending* of text to a channel is handled by a dynamically created [Command](./Commands) that
|
||||
always have the same name as the channel. This is created for each channel by the global
|
||||
`ChannelHandler`. The Channel command is added to the Account's cmdset and normal command locks are
|
||||
used to determine which channels are possible to write to. When subscribing to a channel, you can
|
||||
then just write the channel name and the text to send.
|
||||
|
||||
The default ChannelCommand (which can be customized by pointing `settings.CHANNEL_COMMAND_CLASS` to
|
||||
your own command), implements a few convenient features:
|
||||
|
||||
- It only sends `TempMsg` objects. Instead of storing individual entries in the database it instead
|
||||
dumps channel output a file log in `server/logs/channel_<channelname>.log`. This is mainly for
|
||||
practical reasons - we find one rarely need to query individual Msg objects at a later date. Just
|
||||
stupidly dumping the log to a file also means a lot less database overhead.
|
||||
- It adds a `/history` switch to view the 20 last messages in the channel. These are read from the
|
||||
end of the log file. One can also supply a line number to start further back in the file (but always
|
||||
20 entries at a time). It's used like this:
|
||||
|
||||
> public/history
|
||||
> public/history 35
|
||||
|
||||
|
||||
There are two default channels created in stock Evennia - `MudInfo` and `Public`. `MudInfo`
|
||||
receives server-related messages meant for Admins whereas `Public` is open to everyone to chat on
|
||||
(all new accounts are automatically joined to it when logging in, it is useful for asking
|
||||
questions). The default channels are defined by the `DEFAULT_CHANNELS` list (see
|
||||
`evennia/settings_default.py` for more details).
|
||||
|
||||
You create new channels with `evennia.create_channel` (or `evennia.utils.create.create_channel`).
|
||||
|
||||
In code, messages are sent to a channel using the `msg` or `tempmsg` methods of channels:
|
||||
|
||||
channel.msg(msgobj, header=None, senders=None, persistent=True)
|
||||
|
||||
The argument `msgobj` can be either a string, a previously constructed `Msg` or a `TempMsg` - in the
|
||||
latter cases all the following keywords are ignored since the message objects already contains all
|
||||
this information. If `msgobj` is a string, the other keywords are used for creating a new `Msg` or
|
||||
`TempMsg` on the fly, depending on if `persistent` is set or not. By default, a `TempMsg` is emitted
|
||||
for channel communication (since the default ChannelCommand instead logs to a file).
|
||||
|
||||
```python
|
||||
# assume we have a 'sender' object and a channel named 'mychan'
|
||||
|
||||
# manually sending a message to a channel
|
||||
mychan.msg("Hello!", senders=[sender])
|
||||
```
|
||||
|
||||
### Properties defined on `Channel`
|
||||
|
||||
- `key` - main name for channel
|
||||
- `aliases` - alternative native names for channels
|
||||
- `desc` - optional description of channel (seen in listings)
|
||||
- `keep_log` (bool) - if the channel should store messages (default)
|
||||
- `locks` - A [lock definition](./Locks). Channels normally use the access_types `send, control` and
|
||||
`listen`.
|
||||
- [Channels](./Channels) - are used for implementing in-game chat rooms.
|
||||
- [Msg](./Msg)-objects are used for storing messages in the database (email-like)
|
||||
and is a building block for implementing other game systems. It's used by the
|
||||
`page` command by default.
|
||||
|
|
|
|||
|
|
@ -1,37 +1,164 @@
|
|||
# Help System
|
||||
|
||||
|
||||
An important part of Evennia is the online help system. This allows the players and staff alike to
|
||||
learn how to use the game's commands as well as other information pertinent to the game. The help
|
||||
system has many different aspects, from the normal editing of help entries from inside the game, to
|
||||
auto-generated help entries during code development using the *auto-help system*.
|
||||
|
||||
## Viewing the help database
|
||||
|
||||
The main command is `help`:
|
||||
|
||||
help [searchstring]
|
||||
|
||||
This will show a list of help entries, ordered after categories. You will find two sections,
|
||||
*Command help entries* and *Other help entries* (initially you will only have the first one). You
|
||||
can use help to get more info about an entry; you can also give partial matches to get suggestions.
|
||||
If you give category names you will only be shown the topics in that category.
|
||||
Evennia has an extensive help system covering both command-help and regular
|
||||
free-form help documentation. It supports subtopics and if failing to find a
|
||||
match it will provide suggestsions, first from alternative topics and then by
|
||||
finding mentions of the search term in help entries.
|
||||
|
||||
|
||||
## Command Auto-help system
|
||||
```
|
||||
------------------------------------------------------------------------------
|
||||
Help for The theatre (aliases: the hub, curtains)
|
||||
|
||||
A common item that requires help entries are in-game commands. Keeping these entries up-to-date with
|
||||
the actual source code functionality can be a chore. Evennia's commands are therefore auto-
|
||||
documenting straight from the sources through its *auto-help system*. Only commands that you and
|
||||
your character can actually currently use are picked up by the auto-help system. That means an admin
|
||||
will see a considerably larger amount of help topics than a normal player when using the default
|
||||
`help` command.
|
||||
The theatre is at the centre of the city, both literally and figuratively ...
|
||||
(A lot more text about it follows ...)
|
||||
|
||||
The auto-help system uses the `__doc__` strings of your command classes and formats this to a nice-
|
||||
looking help entry. This makes for a very easy way to keep the help updated - just document your
|
||||
commands well and updating the help file is just a `@reload` away. There is no need to manually
|
||||
create and maintain help database entries for commands; as long as you keep the docstrings updated
|
||||
your help will be dynamically updated for you as well.
|
||||
Subtopics:
|
||||
theatre/lore
|
||||
theatre/layout
|
||||
theatre/dramatis personae
|
||||
------------------------------------------------------------------------------
|
||||
```
|
||||
```
|
||||
------------------------------------------------------------------------------
|
||||
No help found
|
||||
|
||||
There is no help topic matching 'evennia'.
|
||||
... But matches where found within the help texts of the suggestions below.
|
||||
|
||||
Suggestions:
|
||||
grapevine2chan, about, irc2chan
|
||||
-----------------------------------------------------------------------------
|
||||
```
|
||||
|
||||
## Using the help system from in-game
|
||||
|
||||
The help system is accessed in-game by use of the `help` command:
|
||||
|
||||
help <topic>
|
||||
|
||||
Sub-topics are accessed as `help <topic>/<subtopic>/...`.
|
||||
|
||||
Creating a new help entry from in-game is done with
|
||||
|
||||
sethelp <topic>[;aliases] [,category] [,lockstring] = <text>
|
||||
|
||||
For example
|
||||
|
||||
sethelp The Gods;pantheon, Lore = In the beginning all was dark ...
|
||||
|
||||
Use the `/edit` switch to open the EvEditor for more convenient in-game writing
|
||||
(but note that devs can also create help entries outside the game using their
|
||||
regular code editor, see below).
|
||||
|
||||
## Sources of help entries
|
||||
|
||||
Evennia collects help entries from three sources:
|
||||
|
||||
- _Auto-generated command help_ - this is literally the doc-strings of the [Command classes](./Commands).
|
||||
The idea is that the command docs are easier to maintain and keep up-to-date if
|
||||
the developer can change them at the same time as they do the code.
|
||||
- _Database-stored help entries_ - These are created in-game (using the default `sethelp` command
|
||||
as exemplified in the previous section).
|
||||
- _File-stored help entries_ - These are created outside the game, as dicts in
|
||||
normal Python modules. They allows developers to write and maintain their help files using
|
||||
a proper text editor.
|
||||
|
||||
### The Help Entry
|
||||
|
||||
All help entries (no matter the source) have the following properties:
|
||||
|
||||
- `key` - This is the main topic-name. For Commands, this is literally the command's `key`.
|
||||
- `aliases` - Alternate names for the help entry. This can be useful if the main name is hard to remember.
|
||||
- `help_category` - The general grouping of the entry. This is optional. If not given it will use the
|
||||
default category given by `settings.COMMAND_DEFAULT_HELP_CATEGORY` for Commands and `settings.DEFAULT_HELP_CATEGORY`
|
||||
for file+db help entries.
|
||||
- `locks` - This defines who may read this entry. The locktype checked by the `help` command is `view`. In the
|
||||
case of Commands, it's more common that the `cmd` lock fails - in that case the command is not loaded
|
||||
into the help parser at all.
|
||||
- `tags` - This is not used by default, but could be used to further organize help entries.
|
||||
- `text` - The actual help entry text. This will be dedented and stripped of
|
||||
extra space at beginning and end.
|
||||
|
||||
|
||||
A `text` that scrolls off the screen will automatically be paginated by
|
||||
the [EvMore](./EvMore) pager (you can control this with
|
||||
`settings.HELP_MORE_ENABLED=False`). If you use EvMore and want to control
|
||||
exactly where the pager should break the page, mark the break with the control
|
||||
character `\f`.
|
||||
|
||||
|
||||
#### Subtopics
|
||||
|
||||
```versionadded:: 1.0
|
||||
```
|
||||
|
||||
Rather than making a very long help entry, the `text` may also be broken up
|
||||
into _subtopics_. A list of the next level of subtopics are shown below the
|
||||
main help text and allows the user to read more about some particular detail
|
||||
that wouldn't fit in the main text.
|
||||
|
||||
Subtopics use a markup slightly similar to markdown headings. The top level
|
||||
heading must be named `# subtopics` (non case-sensitive) and the following
|
||||
headers must be sub-headings to this (so `## subtopic name` etc). All headings
|
||||
are non-case sensitive (the help command will format them). The topics can be
|
||||
nested at most to a depth of 5 (which is probably too many levels already). The
|
||||
parser uses fuzzy matching to find the subtopic, so one does not have to type
|
||||
it all out exactly.
|
||||
|
||||
Below is an example of a `text` with sub topics.
|
||||
|
||||
|
||||
```
|
||||
The theatre is the heart of the city, here you can find ...
|
||||
(This is the main help text, what you get with `help theatre`)
|
||||
|
||||
# subtopics
|
||||
|
||||
## lore
|
||||
|
||||
The theatre holds many mysterious things...
|
||||
(`help theatre/lore`)
|
||||
|
||||
### the grand opening
|
||||
|
||||
The grand opening is the name for a mysterious event where ghosts appeared ...
|
||||
(`this is a subsub-topic to lore, accessible as `help theatre/lore/grand` or
|
||||
any other partial match).
|
||||
|
||||
### the Phantom
|
||||
|
||||
Deep under the theatre, rumors has it a monster hides ...
|
||||
(another subsubtopic, accessible as `help theatre/lore/phantom`)
|
||||
|
||||
## layout
|
||||
|
||||
The theatre is a two-story building situated at ...
|
||||
(`help theatre/layout`)
|
||||
|
||||
## dramatis personae
|
||||
|
||||
There are many interesting people prowling the halls of the theatre ...
|
||||
(`help theatre/dramatis` or `help theathre/drama` or `help theatre/personae` would work)
|
||||
|
||||
### Primadonna Ada
|
||||
|
||||
Everyone knows the primadonna! She is ...
|
||||
(A subtopic under dramatis personae, accessible as `help theatre/drama/ada` etc)
|
||||
|
||||
### The gatekeeper
|
||||
|
||||
He always keeps an eye on the door and ...
|
||||
(`help theatre/drama/gate`)
|
||||
|
||||
```
|
||||
|
||||
### Command Auto-help system
|
||||
|
||||
The auto-help system uses the `__doc__` strings of your command classes and
|
||||
formats this to a nice- looking help entry. This makes for a very easy way to
|
||||
keep the help updated - just document your commands well and updating the help
|
||||
file is just a `reload` away.
|
||||
|
||||
Example (from a module with command definitions):
|
||||
|
||||
|
|
@ -64,7 +191,8 @@ structure shown above.
|
|||
|
||||
You should also supply the `help_category` class property if you can; this helps to group help
|
||||
entries together for people to more easily find them. See the `help` command in-game to see the
|
||||
default categories. If you don't specify the category, "General" is assumed.
|
||||
default categories. If you don't specify the category, `settings.COMMAND_DEFAULT_HELP_CATEGORY`
|
||||
(default is "General") is used.
|
||||
|
||||
If you don't want your command to be picked up by the auto-help system at all (like if you want to
|
||||
write its docs manually using the info in the next section or you use a [cmdset](./Command-Sets) that
|
||||
|
|
@ -72,51 +200,127 @@ has its own help functionality) you can explicitly set `auto_help` class propert
|
|||
command definition.
|
||||
|
||||
Alternatively, you can keep the advantages of *auto-help* in commands, but control the display of
|
||||
command helps. You can do so by overriding the command's `get_help()` method. By default, this
|
||||
command helps. You can do so by overriding the command's `get_help(caller, cmdset)` method. By default, this
|
||||
method will return the class docstring. You could modify it to add custom behavior: the text
|
||||
returned by this method will be displayed to the character asking for help in this command.
|
||||
|
||||
## Database help entries
|
||||
### Database-help entries
|
||||
|
||||
These are all help entries not involving commands (this is handled automatically by the [Command
|
||||
Auto-help system](Help-System#command-auto-help-system)). Non-automatic help entries describe how
|
||||
your particular game is played - its rules, world descriptions and so on.
|
||||
|
||||
A help entry consists of four parts:
|
||||
|
||||
- The *topic*. This is the name of the help entry. This is what players search for when they are
|
||||
looking for help. The topic can contain spaces and also partial matches will be found.
|
||||
- The *help category*. Examples are *Administration*, *Building*, *Comms* or *General*. This is an
|
||||
overall grouping of similar help topics, used by the engine to give a better overview.
|
||||
- The *text* - the help text itself, of any length.
|
||||
- locks - a [lock definition](./Locks). This can be used to limit access to this help entry, maybe
|
||||
because it's staff-only or otherwise meant to be restricted. Help commands check for `access_type`s
|
||||
`view` and `edit`. An example of a lock string would be `view:perm(Builders)`.
|
||||
|
||||
You can create new help entries in code by using `evennia.create_help_entry()`.
|
||||
These are most commonly created in-game using the `sethelp` command. If you need to create one
|
||||
manually, you can do so with `evennia.create_help_entry()`:
|
||||
|
||||
```python
|
||||
|
||||
from evennia import create_help_entry
|
||||
entry = create_help_entry("emote",
|
||||
"Emoting is important because ...",
|
||||
category="Roleplaying", locks="view:all()")
|
||||
```
|
||||
|
||||
From inside the game those with the right permissions can use the `@sethelp` command to add and
|
||||
modify help entries.
|
||||
The entity being created is a [evennia.help.models.HelpEntry](api:evennia.help.models.HelpEntry)
|
||||
object. This is _not_ a [Typeclassed](./Typeclasses) entity and is not meant to
|
||||
be modified to any great degree. It holds the properties listed earlier. The
|
||||
text is stored in a field `entrytext`. It does not provide a `get_help` method
|
||||
like commands, stores and returns the `entrytext` directly.
|
||||
|
||||
> @sethelp/add emote = The emote command is ...
|
||||
You can search for `HelpEntry` objects using `evennia.search_help` but note
|
||||
that this will not return the two other types of help entries.
|
||||
|
||||
Using `@sethelp` you can add, delete and append text to existing entries. By default new entries
|
||||
will go in the *General* help category. You can change this using a different form of the `@sethelp`
|
||||
command:
|
||||
|
||||
> @sethelp/add emote, Roleplaying = Emoting is important because ...
|
||||
### File-help entries
|
||||
|
||||
If the category *Roleplaying* did not already exist, it is created and will appear in the help
|
||||
index.
|
||||
```versionadded:: 1.0
|
||||
```
|
||||
|
||||
You can, finally, define a lock for the help entry by following the category with a [lock
|
||||
definition](Locks):
|
||||
File-help entries are created by the game development team outside of the game. The
|
||||
help entries are defined in normal Python modules (`.py` file ending) containing
|
||||
a `dict` to represent each entry. They require a server `reload` before any changes
|
||||
apply.
|
||||
|
||||
> @sethelp/add emote, Roleplaying, view:all() = Emoting is ...
|
||||
- Evennia will look through all modules given by `settings.FILE_HELP_ENTRY_MODULES`. This
|
||||
should be a list of python-paths for Evennia to import.
|
||||
- If this module contains a top-level variable `HELP_ENTRY_DICTS`, this will be imported
|
||||
and must be a `list` of help-entry dicts.
|
||||
- If no `HELP_ENTRY_DICTS` list is found, _every_ top-level variable in the
|
||||
module that is a `dict` will be read as a help entry. The variable-names will
|
||||
be ignored in this case.
|
||||
|
||||
If you add multiple modules to be read, same-keyed help entries added later in the list
|
||||
will override coming before.
|
||||
|
||||
Each entry dict must define keys to match that needed by all help entries.
|
||||
Here's an example of a help module:
|
||||
|
||||
```python
|
||||
|
||||
# in a module pointed to by settings.FILE_HELP_ENTRY_MODULES
|
||||
|
||||
HELP_ENTRY_DICTS = [
|
||||
{
|
||||
"key": "The Gods", # case-insensitive, can be searched by 'gods' too
|
||||
"aliases": ['pantheon', 'religion']
|
||||
"category": "Lore",
|
||||
"text": '''
|
||||
The gods formed the world ...
|
||||
|
||||
# Subtopics
|
||||
|
||||
## Pantheon
|
||||
|
||||
The pantheon consists of 40 gods that ...
|
||||
|
||||
### God of love
|
||||
|
||||
The most prominent god is ...
|
||||
|
||||
### God of war
|
||||
|
||||
Also known as 'the angry god', this god is known to ...
|
||||
|
||||
'''
|
||||
},
|
||||
{
|
||||
"key": "The mortals",
|
||||
|
||||
}
|
||||
]
|
||||
|
||||
```
|
||||
|
||||
The help entry text will be dedented and will retain paragraphs. You should try
|
||||
to keep your strings a reasonable width (it will look better). Just reload the
|
||||
server and the file-based help entries will be available to view.
|
||||
|
||||
|
||||
## Customizing the look of the help system
|
||||
|
||||
This is done almost exclusively by overriding the `help` command
|
||||
[evennia.commands.default.help.CmdHelp](api:evennia.commands.default.help#CmdHelp).
|
||||
|
||||
Since the available commands may vary from moment to moment, `help` is
|
||||
responsible for collating the three sources of help-entries (commands/db/file)
|
||||
together and search through them on the fly. It also does all the formatting of
|
||||
the output.
|
||||
|
||||
To make it easier to tweak the look, the parts of the code that changes the
|
||||
visual presentation has been broken out into separate methods `format_help_entry` and
|
||||
`format_help_index` - override these in your version of `help` to change the display
|
||||
as you please. See the api link above for details.
|
||||
|
||||
|
||||
## Technical notes
|
||||
|
||||
Since it needs to search so different types of data, the help system has to
|
||||
collect all possibilities in memory before searching through the entire set. It
|
||||
uses the [Lunr](https://github.com/yeraydiazdiaz/lunr.py) search engine to
|
||||
search through the main bulk of help entries. Lunr is a mature engine used for
|
||||
web-pages and produces much more sensible results than previous solutions.
|
||||
|
||||
Once the main entry has been found, subtopics are then searched with
|
||||
simple `==`, `startswith` and `in` matching (there are so relatively few of them
|
||||
at that point).
|
||||
|
||||
```versionchanged:: 1.0
|
||||
Replaced the bag-of-words algorithm with lunr.
|
||||
|
||||
```
|
||||
|
|
|
|||
91
docs/1.0-dev/_sources/Components/Msg.md.txt
Normal file
91
docs/1.0-dev/_sources/Components/Msg.md.txt
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
# Msg
|
||||
|
||||
The [Msg](api:evennia.comms.models.Msg) object represents a database-saved
|
||||
piece of communication. Think of it as a discrete piece of email - it contains
|
||||
a message, some metadata and will always have a sender and one or more
|
||||
recipients.
|
||||
|
||||
Once created, a Msg is normally not changed. It is persitently saved in the
|
||||
database. This allows for comprehensive logging of communications. Here are some
|
||||
good uses for `Msg` objects:
|
||||
|
||||
- page/tells (the `page` command is how Evennia uses them out of the box)
|
||||
- messages in a bulletin board
|
||||
- game-wide email stored in 'mailboxes'.
|
||||
|
||||
|
||||
```important::
|
||||
|
||||
A `Msg` does not have any in-game representation. So if you want to use them
|
||||
to represent in-game mail/letters, the physical letters would never be
|
||||
visible in a room (possible to steal, spy on etc) unless you make your
|
||||
spy-system access the Msgs directly (or go to the trouble of spawning an
|
||||
actual in-game letter-object based on the Msg)
|
||||
|
||||
|
||||
```
|
||||
|
||||
```versionchanged:: 1.0
|
||||
Channels dropped Msg-support. Now only used in `page` command by default.
|
||||
```
|
||||
|
||||
## Msg in code
|
||||
|
||||
The Msg is intended to be used exclusively in code, to build other game systems. It is _not_
|
||||
a [Typeclassed](./Typeclasses) entity, which means it cannot (easily) be overridden. It
|
||||
doesn't support Attributes (but it _does_ support [Tags](./Tags)). It tries to be lean
|
||||
and small since a new one is created for every message.
|
||||
|
||||
You create a new message with `evennia.create_message`:
|
||||
|
||||
```python
|
||||
from evennia import create_message
|
||||
message = create_message(senders, message, receivers,
|
||||
locks=..., tags=..., header=...)
|
||||
```
|
||||
|
||||
You can search for `Msg` objects in various ways:
|
||||
|
||||
|
||||
```python
|
||||
from evennia import search_message, Msg
|
||||
|
||||
# args are optional. Only a single sender/receiver should be passed
|
||||
messages = search_message(sender=..., receiver=..., freetext=..., dbref=...)
|
||||
|
||||
# get all messages for a given sender/receiver
|
||||
messages = Msg.objects.get_msg_by_sender(sender)
|
||||
messages = Msg.objects.get_msg_by_receiver(recipient)
|
||||
|
||||
```
|
||||
|
||||
### Properties on Msg
|
||||
|
||||
- `senders` - there must always be at least one sender. This is one of [Account](./Accounts), [Object](./Objects), [Script](./Scripts)
|
||||
or _external_ - which is a string uniquely identifying the sender. The latter can be used by
|
||||
a sender-system that doesn't fit into Evennia's normal typeclass-system.
|
||||
While most systems expect a single sender, it's possible to have any number of them.
|
||||
- `receivers` - these are the ones to see the Msg. These are again one of
|
||||
[Account](./Accounts), [Object](./Objects) or [Script](./Scripts). It's in principle possible to have
|
||||
zero receivers but most usages of Msg expects one or more.
|
||||
- `header` - this is an optional text field that can contain meta-information about the message. For
|
||||
an email-like system it would be the subject line. This can be independently searched, making
|
||||
this a powerful place for quickly finding messages.
|
||||
- `message` - the actual text being sent.
|
||||
- `date_sent` - this is auto-set to the time the Msg was created (and thus presumably sent).
|
||||
- `locks` - the Evennia [lock handler](./Locks). Use with `locks.add()` etc and check locks with `msg.access()`
|
||||
like for all other lockable entities. This can be used to limit access to the contents
|
||||
of the Msg. The default lock-type to check is `'read'`.
|
||||
- `hide_from` - this is an optional list of [Accounts](./Accounts) or [Objects](./Objects) that
|
||||
will not see this Msg. This relationship is available mainly for optimization
|
||||
reasons since it allows quick filtering of messages not intended for a given
|
||||
target.
|
||||
|
||||
|
||||
## TempMsg
|
||||
|
||||
[evennia.comms.models.TempMsg](api:evennia.comms.models.TempMsg) is an object
|
||||
that implements the same API as the regular `Msg`, but which has no database
|
||||
component (and thus cannot be searched). It's meant to plugged into systems
|
||||
expecting a `Msg` but where you just want to process the message without saving
|
||||
it.
|
||||
Loading…
Add table
Add a link
Reference in a new issue