Fixed all links

This commit is contained in:
Griatch 2020-10-11 19:31:05 +02:00
parent d4f1733bc7
commit 26f8ba3f71
175 changed files with 11972 additions and 4443 deletions

View file

@ -1,46 +1,72 @@
# Evennia for roleplaying sessions
This tutorial will explain how to set up a realtime or play-by-post tabletop style game using a fresh Evennia server.
This tutorial will explain how to set up a realtime or play-by-post tabletop style game using a
fresh Evennia server.
The scenario is thus: You and a bunch of friends want to play a tabletop role playing game online. One of you will be the game master and you are all okay with playing using written text. You want both the ability to role play in real-time (when people happen to be online at the same time) as well as the ability for people to post when they can and catch up on what happened since they were last online.
The scenario is thus: You and a bunch of friends want to play a tabletop role playing game online.
One of you will be the game master and you are all okay with playing using written text. You want
both the ability to role play in real-time (when people happen to be online at the same time) as
well as the ability for people to post when they can and catch up on what happened since they were
last online.
This is the functionality we will be needing and using:
* The ability to make one of you the *GM* (game master), with special abilities.
* A *Character sheet* that players can create, view and fill in. It can also be locked so only the GM can modify it.
* A *Character sheet* that players can create, view and fill in. It can also be locked so only the
GM can modify it.
* A *dice roller* mechanism, for whatever type of dice the RPG rules require.
* *Rooms*, to give a sense of location and to compartmentalize play going on- This means both Character movements from location to location and GM explicitly moving them around.
* *Rooms*, to give a sense of location and to compartmentalize play going on- This means both
Character movements from location to location and GM explicitly moving them around.
* *Channels*, for easily sending text to all subscribing accounts, regardless of location.
* Account-to-Account *messaging* capability, including sending to multiple recipients simultaneously, regardless of location.
* Account-to-Account *messaging* capability, including sending to multiple recipients
simultaneously, regardless of location.
We will find most of these things are already part of vanilla Evennia, but that we can expand on the defaults for our particular use-case. Below we will flesh out these components from start to finish.
We will find most of these things are already part of vanilla Evennia, but that we can expand on the
defaults for our particular use-case. Below we will flesh out these components from start to finish.
## Starting out
We will assume you start from scratch. You need Evennia installed, as per the [Getting Started](./Getting-Started) instructions. Initialize a new game directory with `evennia init <gamedirname>`. In this tutorial we assume your game dir is simply named `mygame`. You can use the default database and keep all other settings to default for now. Familiarize yourself with the `mygame` folder before continuing. You might want to browse the [First Steps Coding](./First-Steps-Coding) tutorial, just to see roughly where things are modified.
We will assume you start from scratch. You need Evennia installed, as per the [Getting
Started](Getting-Started) instructions. Initialize a new game directory with `evennia init
<gamedirname>`. In this tutorial we assume your game dir is simply named `mygame`. You can use the
default database and keep all other settings to default for now. Familiarize yourself with the
`mygame` folder before continuing. You might want to browse the [First Steps Coding](First-Steps-
Coding) tutorial, just to see roughly where things are modified.
## The Game Master role
In brief:
In brief:
* Simplest way: Being an admin, just give one account `Admins` permission using the standard `@perm` command.
* Better but more work: Make a custom command to set/unset the above, while tweaking the Character to show your renewed GM status to the other accounts.
* Simplest way: Being an admin, just give one account `Admins` permission using the standard `@perm`
command.
* Better but more work: Make a custom command to set/unset the above, while tweaking the Character
to show your renewed GM status to the other accounts.
### The permission hierarchy
Evennia has the following [permission hierarchy](./Building-Permissions#assigning-permissions) out of the box: *Players, Helpers, Builders, Admins* and finally *Developers*. We could change these but then we'd need to update our Default commands to use the changes. We want to keep this simple, so instead we map our different roles on top of this permission ladder.
Evennia has the following [permission hierarchy](./Building-Permissions#assigning-permissions) out of
the box: *Players, Helpers, Builders, Admins* and finally *Developers*. We could change these but
then we'd need to update our Default commands to use the changes. We want to keep this simple, so
instead we map our different roles on top of this permission ladder.
1. `Players` is the permission set on normal players. This is the default for anyone creating a new account on the server.
2. `Helpers` are like `Players` except they also have the ability to create/edit new help entries. This could be granted to players who are willing to help with writing lore or custom logs for everyone.
1. `Players` is the permission set on normal players. This is the default for anyone creating a new
account on the server.
2. `Helpers` are like `Players` except they also have the ability to create/edit new help entries.
This could be granted to players who are willing to help with writing lore or custom logs for
everyone.
3. `Builders` is not used in our case since the GM should be the only world-builder.
4. `Admins` is the permission level the GM should have. Admins can do everything builders can (create/describe rooms etc) but also kick accounts, rename them and things like that.
5. `Developers`-level permission are the server administrators, the ones with the ability to restart/shutdown the server as well as changing the permission levels.
4. `Admins` is the permission level the GM should have. Admins can do everything builders can
(create/describe rooms etc) but also kick accounts, rename them and things like that.
5. `Developers`-level permission are the server administrators, the ones with the ability to
restart/shutdown the server as well as changing the permission levels.
> The [superuser](./Building-Permissions#the-super-user) is not part of the hierarchy and actually completely bypasses it. We'll assume server admin(s) will "just" be Developers.
> The [superuser](./Building-Permissions#the-super-user) is not part of the hierarchy and actually
completely bypasses it. We'll assume server admin(s) will "just" be Developers.
### How to grant permissions
Only `Developers` can (by default) change permission level. Only they have access to the `@perm` command:
Only `Developers` can (by default) change permission level. Only they have access to the `@perm`
command:
```
> @perm Yvonne
@ -55,21 +81,30 @@ Permissions on Yvonne: accounts, admins
Permissions on Yvonne: accounts
```
There is no need to remove the basic `Players` permission when adding the higher permission: the highest will be used. Permission level names are *not* case sensitive. You can also use both plural and singular, so "Admins" gives the same powers as "Admin".
There is no need to remove the basic `Players` permission when adding the higher permission: the
highest will be used. Permission level names are *not* case sensitive. You can also use both plural
and singular, so "Admins" gives the same powers as "Admin".
### Optional: Making a GM-granting command
Use of `@perm` works out of the box, but it's really the bare minimum. Would it not be nice if other accounts could tell at a glance who the GM is? Also, we shouldn't really need to remember that the permission level is called "Admins". It would be easier if we could just do `@gm <account>` and `@notgm <account>` and at the same time change something make the new GM status apparent.
Use of `@perm` works out of the box, but it's really the bare minimum. Would it not be nice if other
accounts could tell at a glance who the GM is? Also, we shouldn't really need to remember that the
permission level is called "Admins". It would be easier if we could just do `@gm <account>` and
`@notgm <account>` and at the same time change something make the new GM status apparent.
So let's make this possible. This is what we'll do:
1. We'll customize the default Character class. If an object of this class has a particular flag, its name will have the string`(GM)` added to the end.
1. We'll customize the default Character class. If an object of this class has a particular flag,
its name will have the string`(GM)` added to the end.
2. We'll add a new command, for the server admin to assign the GM-flag properly.
#### Character modification
Let's first start by customizing the Character. We recommend you browse the beginning of the [Account](./Accounts) page to make sure you know how Evennia differentiates between the OOC "Account objects" (not to be confused with the `Accounts` permission, which is just a string specifying your access) and the IC "Character objects".
Let's first start by customizing the Character. We recommend you browse the beginning of the
[Account](./Accounts) page to make sure you know how Evennia differentiates between the OOC "Account
objects" (not to be confused with the `Accounts` permission, which is just a string specifying your
access) and the IC "Character objects".
Open `mygame/typeclasses/characters.py` and modify the default `Character` class:
@ -103,13 +138,23 @@ class Character(DefaultCharacter):
```
Above, we change how the Character's name is displayed: If the account controlling this Character is a GM, we attach the string `(GM)` to the Character's name so everyone can tell who's the boss. If we ourselves are Developers or GM's we will see database ids attached to Characters names, which can help if doing database searches against Characters of exactly the same name. We base the "gm-ingness" on having an flag (an [Attribute](./Attributes)) named `is_gm`. We'll make sure new GM's actually get this flag below.
Above, we change how the Character's name is displayed: If the account controlling this Character is
a GM, we attach the string `(GM)` to the Character's name so everyone can tell who's the boss. If we
ourselves are Developers or GM's we will see database ids attached to Characters names, which can
help if doing database searches against Characters of exactly the same name. We base the "gm-
ingness" on having an flag (an [Attribute](./Attributes)) named `is_gm`. We'll make sure new GM's
actually get this flag below.
> **Extra exercise:** This will only show the `(GM)` text on *Characters* puppeted by a GM account, that is, it will show only to those in the same location. If we wanted it to also pop up in, say, `who` listings and channels, we'd need to make a similar change to the `Account` typeclass in `mygame/typeclasses/accounts.py`. We leave this as an exercise to the reader.
> **Extra exercise:** This will only show the `(GM)` text on *Characters* puppeted by a GM account,
that is, it will show only to those in the same location. If we wanted it to also pop up in, say,
`who` listings and channels, we'd need to make a similar change to the `Account` typeclass in
`mygame/typeclasses/accounts.py`. We leave this as an exercise to the reader.
#### New @gm/@ungm command
We will describe in some detail how to create and add an Evennia [command](./Commands) here with the hope that we don't need to be as detailed when adding commands in the future. We will build on Evennia's default "mux-like" commands here.
We will describe in some detail how to create and add an Evennia [command](./Commands) here with the
hope that we don't need to be as detailed when adding commands in the future. We will build on
Evennia's default "mux-like" commands here.
Open `mygame/commands/command.py` and add a new Command class at the bottom:
@ -176,11 +221,17 @@ class CmdMakeGM(default_cmds.MuxCommand):
```
All the command does is to locate the account target and assign it the `Admins` permission if we used `@gm` or revoke it if using the `@ungm` alias. We also set/unset the `is_gm` Attribute that is expected by our new `Character.get_display_name` method from earlier.
All the command does is to locate the account target and assign it the `Admins` permission if we
used `@gm` or revoke it if using the `@ungm` alias. We also set/unset the `is_gm` Attribute that is
expected by our new `Character.get_display_name` method from earlier.
> We could have made this into two separate commands or opted for a syntax like `@gm/revoke <accountname>`. Instead we examine how this command was called (stored in `self.cmdstring`) in order to act accordingly. Either way works, practicality and coding style decides which to go with.
> We could have made this into two separate commands or opted for a syntax like `@gm/revoke
<accountname>`. Instead we examine how this command was called (stored in `self.cmdstring`) in order
to act accordingly. Either way works, practicality and coding style decides which to go with.
To actually make this command available (only to Developers, due to the lock on it), we add it to the default Account command set. Open the file `mygame/commands/default_cmdsets.py` and find the `AccountCmdSet` class:
To actually make this command available (only to Developers, due to the lock on it), we add it to
the default Account command set. Open the file `mygame/commands/default_cmdsets.py` and find the
`AccountCmdSet` class:
```python
# mygame/commands/default_cmdsets.py
@ -196,11 +247,12 @@ class AccountCmdSet(default_cmds.AccountCmdSet):
```
Finally, issue the `@reload` command to update the server to your changes. Developer-level players (or the superuser) should now have the `@gm/@ungm` command available.
Finally, issue the `@reload` command to update the server to your changes. Developer-level players
(or the superuser) should now have the `@gm/@ungm` command available.
## Character sheet
In brief:
In brief:
* Use Evennia's EvTable/EvForm to build a Character sheet
* Tie individual sheets to a given Character.
@ -209,13 +261,18 @@ In brief:
### Building a Character sheet
There are many ways to build a Character sheet in text, from manually pasting strings together to more automated ways. Exactly what is the best/easiest way depends on the sheet one tries to create. We will here show two examples using the *EvTable* and *EvForm* utilities.Later we will create Commands to edit and display the output from those utilities.
There are many ways to build a Character sheet in text, from manually pasting strings together to
more automated ways. Exactly what is the best/easiest way depends on the sheet one tries to create.
We will here show two examples using the *EvTable* and *EvForm* utilities.Later we will create
Commands to edit and display the output from those utilities.
> Note that due to the limitations of the wiki, no color is used in any of the examples. See [the text tag documentation](./TextTags) for how to add color to the tables and forms.
> Note that due to the limitations of the wiki, no color is used in any of the examples. See [the
text tag documentation](TextTags) for how to add color to the tables and forms.
#### Making a sheet with EvTable
[EvTable](github:evennia.utils.evtable) is a text-table generator. It helps with displaying text in ordered rows and columns. This is an example of using it in code:
[EvTable](github:evennia.utils.evtable) is a text-table generator. It helps with displaying text in
ordered rows and columns. This is an example of using it in code:
````python
# this can be tried out in a Python shell like iPython
@ -232,7 +289,13 @@ table = evtable.EvTable("Attr", "Value",
], align='r', border="incols")
````
Above, we create a two-column table by supplying the two columns directly. We also tell the table to be right-aligned and to use the "incols" border type (borders drawns only in between columns). The `EvTable` class takes a lot of arguments for customizing its look, you can see [some of the possible keyword arguments here](github:evennia.utils.evtable#evtable__init__). Once you have the `table` you could also retroactively add new columns and rows to it with `table.add_row()` and `table.add_column()`: if necessary the table will expand with empty rows/columns to always remain rectangular.
Above, we create a two-column table by supplying the two columns directly. We also tell the table to
be right-aligned and to use the "incols" border type (borders drawns only in between columns). The
`EvTable` class takes a lot of arguments for customizing its look, you can see [some of the possible
keyword arguments here](github:evennia.utils.evtable#evtable__init__). Once you have the `table` you
could also retroactively add new columns and rows to it with `table.add_row()` and
`table.add_column()`: if necessary the table will expand with empty rows/columns to always remain
rectangular.
The result from printing the above table will be
@ -251,17 +314,29 @@ print(table_string)
CHA | 13
```
This is a minimalistic but effective Character sheet. By combining the `table_string` with other strings one could build up a reasonably full graphical representation of a Character. For more advanced layouts we'll look into EvForm next.
This is a minimalistic but effective Character sheet. By combining the `table_string` with other
strings one could build up a reasonably full graphical representation of a Character. For more
advanced layouts we'll look into EvForm next.
#### Making a sheet with EvForm
[EvForm](github:evennia.utils.evform) allows the creation of a two-dimensional "graphic" made by text characters. On this surface, one marks and tags rectangular regions ("cells") to be filled with content. This content can be either normal strings or `EvTable` instances (see the previous section, one such instance would be the `table` variable in that example).
[EvForm](github:evennia.utils.evform) allows the creation of a two-dimensional "graphic" made by
text characters. On this surface, one marks and tags rectangular regions ("cells") to be filled with
content. This content can be either normal strings or `EvTable` instances (see the previous section,
one such instance would be the `table` variable in that example).
In the case of a Character sheet, these cells would be comparable to a line or box where you could enter the name of your character or their strength score. EvMenu also easily allows to update the content of those fields in code (it use EvTables so you rebuild the table first before re-sending it to EvForm).
In the case of a Character sheet, these cells would be comparable to a line or box where you could
enter the name of your character or their strength score. EvMenu also easily allows to update the
content of those fields in code (it use EvTables so you rebuild the table first before re-sending it
to EvForm).
The drawback of EvForm is that its shape is static; if you try to put more text in a region than it was sized for, the text will be cropped. Similarly, if you try to put an EvTable instance in a field too small for it, the EvTable will do its best to try to resize to fit, but will eventually resort to cropping its data or even give an error if too small to fit any data.
The drawback of EvForm is that its shape is static; if you try to put more text in a region than it
was sized for, the text will be cropped. Similarly, if you try to put an EvTable instance in a field
too small for it, the EvTable will do its best to try to resize to fit, but will eventually resort
to cropping its data or even give an error if too small to fit any data.
An EvForm is defined in a Python module. Create a new file `mygame/world/charsheetform.py` and modify it thus:
An EvForm is defined in a Python module. Create a new file `mygame/world/charsheetform.py` and
modify it thus:
````python
#coding=utf-8
@ -291,9 +366,16 @@ FORM = """
+--------------------------------------+
"""
````
The `#coding` statement (which must be put on the very first line to work) tells Python to use the utf-8 encoding for the file. Using the `FORMCHAR` and `TABLECHAR` we define what single-character we want to use to "mark" the regions of the character sheet holding cells and tables respectively. Within each block (which must be separated from one another by at least one non-marking character) we embed identifiers 1-4 to identify each block. The identifier could be any single character except for the `FORMCHAR` and `TABLECHAR`
The `#coding` statement (which must be put on the very first line to work) tells Python to use the
utf-8 encoding for the file. Using the `FORMCHAR` and `TABLECHAR` we define what single-character we
want to use to "mark" the regions of the character sheet holding cells and tables respectively.
Within each block (which must be separated from one another by at least one non-marking character)
we embed identifiers 1-4 to identify each block. The identifier could be any single character except
for the `FORMCHAR` and `TABLECHAR`
> You can still use `FORMCHAR` and `TABLECHAR` elsewhere in your sheet, but not in a way that it would identify a cell/table. The smallest identifiable cell/table area is 3 characters wide including the identifier (for example `x2x`).
> You can still use `FORMCHAR` and `TABLECHAR` elsewhere in your sheet, but not in a way that it
would identify a cell/table. The smallest identifiable cell/table area is 3 characters wide
including the identifier (for example `x2x`).
Now we will map content to this form.
@ -318,9 +400,13 @@ form.map(cells={"1":NAME, "3": ADVANTAGES, "4": DISADVANTAGES},
tables={"2":table})
````
We create some RP-sounding input and re-use the `table` variable from the previous `EvTable` example.
We create some RP-sounding input and re-use the `table` variable from the previous `EvTable`
example.
> Note, that if you didn't want to create the form in a separate module you *could* also load it directly into the `EvForm` call like this: `EvForm(form={"FORMCHAR":"x", "TABLECHAR":"c", "FORM": formstring})` where `FORM` specifies the form as a string in the same way as listed in the module above. Note however that the very first line of the `FORM` string is ignored, so start with a `\n`.
> Note, that if you didn't want to create the form in a separate module you *could* also load it
directly into the `EvForm` call like this: `EvForm(form={"FORMCHAR":"x", "TABLECHAR":"c", "FORM":
formstring})` where `FORM` specifies the form as a string in the same way as listed in the module
above. Note however that the very first line of the `FORM` string is ignored, so start with a `\n`.
We then map those to the cells of the form:
@ -347,11 +433,15 @@ print(form)
+--------------------------------------+
````
As seen, the texts and tables have been slotted into the text areas and line breaks have been added where needed. We chose to just enter the Advantages/Disadvantages as plain strings here, meaning long names ended up split between rows. If we wanted more control over the display we could have inserted `\n` line breaks after each line or used a borderless `EvTable` to display those as well.
As seen, the texts and tables have been slotted into the text areas and line breaks have been added
where needed. We chose to just enter the Advantages/Disadvantages as plain strings here, meaning
long names ended up split between rows. If we wanted more control over the display we could have
inserted `\n` line breaks after each line or used a borderless `EvTable` to display those as well.
### Tie a Character sheet to a Character
We will assume we go with the `EvForm` example above. We now need to attach this to a Character so it can be modified. For this we will modify our `Character` class a little more:
We will assume we go with the `EvForm` example above. We now need to attach this to a Character so
it can be modified. For this we will modify our `Character` class a little more:
```python
# mygame/typeclasses/character.py
@ -397,7 +487,10 @@ class Character(DefaultCharacter):
```
Use `@reload` to make this change available to all *newly created* Characters. *Already existing* Characters will *not* have the charsheet defined, since `at_object_creation` is only called once. The easiest to force an existing Character to re-fire its `at_object_creation` is to use the `@typeclass` command in-game:
Use `@reload` to make this change available to all *newly created* Characters. *Already existing*
Characters will *not* have the charsheet defined, since `at_object_creation` is only called once.
The easiest to force an existing Character to re-fire its `at_object_creation` is to use the
`@typeclass` command in-game:
```
@typeclass/force <Character Name>
@ -405,7 +498,8 @@ Use `@reload` to make this change available to all *newly created* Characters. *
### Command for Account to change Character sheet
We will add a command to edit the sections of our Character sheet. Open `mygame/commands/command.py`.
We will add a command to edit the sections of our Character sheet. Open
`mygame/commands/command.py`.
```python
# at the end of mygame/commands/command.py
@ -480,13 +574,16 @@ class CmdSheet(MuxCommand):
```
Most of this command is error-checking to make sure the right type of data was input. Note how the `sheet_locked` Attribute is checked and will return if not set.
Most of this command is error-checking to make sure the right type of data was input. Note how the
`sheet_locked` Attribute is checked and will return if not set.
This command you import into `mygame/commands/default_cmdsets.py` and add to the `CharacterCmdSet`, in the same way the `@gm` command was added to the `AccountCmdSet` earlier.
This command you import into `mygame/commands/default_cmdsets.py` and add to the `CharacterCmdSet`,
in the same way the `@gm` command was added to the `AccountCmdSet` earlier.
### Commands for GM to change Character sheet
Game masters use basically the same input as Players do to edit a character sheet, except they can do it on other players than themselves. They are also not stopped by any `sheet_locked` flags.
Game masters use basically the same input as Players do to edit a character sheet, except they can
do it on other players than themselves. They are also not stopped by any `sheet_locked` flags.
```python
# continuing in mygame/commands/command.py
@ -564,44 +661,63 @@ class CmdGMsheet(MuxCommand):
caller.msg(character.db.charsheet)
```
The `@gmsheet` command takes an additional argument to specify which Character's character sheet to edit. It also takes `/lock` and `/unlock` switches to block the Player from tweaking their sheet.
The `@gmsheet` command takes an additional argument to specify which Character's character sheet to
edit. It also takes `/lock` and `/unlock` switches to block the Player from tweaking their sheet.
Before this can be used, it should be added to the default `CharacterCmdSet` in the same way as the normal `@sheet`. Due to the lock set on it, this command will only be available to `Admins` (i.e. GMs) or higher permission levels.
Before this can be used, it should be added to the default `CharacterCmdSet` in the same way as the
normal `@sheet`. Due to the lock set on it, this command will only be available to `Admins` (i.e.
GMs) or higher permission levels.
## Dice roller
Evennia's *contrib* folder already comes with a full dice roller. To add it to the game, simply import `contrib.dice.CmdDice` into `mygame/commands/default_cmdsets.py` and add `CmdDice` to the `CharacterCmdset` as done with other commands in this tutorial. After a `@reload` you will be able to roll dice using normal RPG-style format:
Evennia's *contrib* folder already comes with a full dice roller. To add it to the game, simply
import `contrib.dice.CmdDice` into `mygame/commands/default_cmdsets.py` and add `CmdDice` to the
`CharacterCmdset` as done with other commands in this tutorial. After a `@reload` you will be able
to roll dice using normal RPG-style format:
```
roll 2d6 + 3
7
```
Use `help dice` to see what syntax is supported or look at `evennia/contrib/dice.py` to see how it's implemented.
Use `help dice` to see what syntax is supported or look at `evennia/contrib/dice.py` to see how it's
implemented.
## Rooms
Evennia comes with rooms out of the box, so no extra work needed. A GM will automatically have all needed building commands available. A fuller go-through is found in the [Building tutorial](./Building-Quickstart). Here are some useful highlights:
Evennia comes with rooms out of the box, so no extra work needed. A GM will automatically have all
needed building commands available. A fuller go-through is found in the [Building
tutorial](Building-Quickstart). Here are some useful highlights:
* `@dig roomname;alias = exit_there;alias, exit_back;alias` - this is the basic command for digging a new room. You can specify any exit-names and just enter the name of that exit to go there.
* `@tunnel direction = roomname` - this is a specialized command that only accepts directions in the cardinal directions (n,ne,e,se,s,sw,w,nw) as well as in/out and up/down. It also automatically builds "matching" exits back in the opposite direction.
* `@dig roomname;alias = exit_there;alias, exit_back;alias` - this is the basic command for digging
a new room. You can specify any exit-names and just enter the name of that exit to go there.
* `@tunnel direction = roomname` - this is a specialized command that only accepts directions in the
cardinal directions (n,ne,e,se,s,sw,w,nw) as well as in/out and up/down. It also automatically
builds "matching" exits back in the opposite direction.
* `@create/drop objectname` - this creates and drops a new simple object in the current location.
* `@desc obj` - change the look-description of the object.
* `@tel object = location` - teleport an object to a named location.
* `@search objectname` - locate an object in the database.
> TODO: Describe how to add a logging room, that logs says and poses to a log file that people can access after the fact.
> TODO: Describe how to add a logging room, that logs says and poses to a log file that people can
access after the fact.
## Channels
Evennia comes with [Channels](./Communications#Channels) in-built and they are described fully in the documentation. For brevity, here are the relevant commands for normal use:
Evennia comes with [Channels](./Communications#Channels) in-built and they are described fully in the
documentation. For brevity, here are the relevant commands for normal use:
* `@ccreate new_channel;alias;alias = short description` - Creates a new channel.
* `addcom channel` - join an existing channel. Use `addcom alias = channel` to add a new alias you can use to talk to the channel, as many as desired.
* `delcom alias or channel` - remove an alias from a channel or, if the real channel name is given, unsubscribe completely.
* `@channels` lists all available channels, including your subscriptions and any aliases you have set up for them.
* `addcom channel` - join an existing channel. Use `addcom alias = channel` to add a new alias you
can use to talk to the channel, as many as desired.
* `delcom alias or channel` - remove an alias from a channel or, if the real channel name is given,
unsubscribe completely.
* `@channels` lists all available channels, including your subscriptions and any aliases you have
set up for them.
You can read channel history: if you for example are chatting on the `public` channel you can do `public/history` to see the 20 last posts to that channel or `public/history 32` to view twenty posts backwards, starting with the 32nd from the end.
You can read channel history: if you for example are chatting on the `public` channel you can do
`public/history` to see the 20 last posts to that channel or `public/history 32` to view twenty
posts backwards, starting with the 32nd from the end.
## PMs
@ -612,4 +728,5 @@ page recipient = message
page recipient, recipient, ... = message
```
Players can use `page` alone to see the latest messages. This also works if they were not online when the message was sent.
Players can use `page` alone to see the latest messages. This also works if they were not online
when the message was sent.