From 77b0e26b70e7b036162edd3f85531acc30fdd96c Mon Sep 17 00:00:00 2001 From: Evennia docbuilder action Date: Sat, 15 Jul 2023 20:42:40 +0000 Subject: [PATCH] Updated HTML docs. --- docs/2.x/.buildinfo | 2 +- docs/2.x/Contribs/Contrib-Llm.html | 4 +- .../evennia/contrib/rpg/llm/llm_client.html | 77 +++++++++++------- .../evennia/contrib/rpg/llm/llm_npc.html | 38 ++++++++- docs/2.x/_sources/Contribs/Contrib-Llm.md.txt | 4 +- .../api/evennia.commands.default.account.html | 4 +- .../evennia.commands.default.building.html | 4 +- .../api/evennia.commands.default.comms.html | 8 +- .../api/evennia.commands.default.general.html | 12 +-- .../api/evennia.commands.default.system.html | 4 +- .../api/evennia.commands.default.tests.html | 2 +- .../evennia.commands.default.unloggedin.html | 8 +- ....base_systems.email_login.email_login.html | 8 +- ...b.base_systems.ingame_python.commands.html | 4 +- ...systems.mux_comms_cmds.mux_comms_cmds.html | 8 +- ...rib.full_systems.evscaperoom.commands.html | 20 ++--- ...ontrib.game_systems.clothing.clothing.html | 4 +- ...trib.game_systems.turnbattle.tb_basic.html | 4 +- ...trib.game_systems.turnbattle.tb_equip.html | 4 +- ...trib.game_systems.turnbattle.tb_items.html | 4 +- ...trib.game_systems.turnbattle.tb_magic.html | 4 +- ...trib.game_systems.turnbattle.tb_range.html | 4 +- ...trib.grid.extended_room.extended_room.html | 4 +- ...evennia.contrib.grid.xyzgrid.commands.html | 4 +- .../api/evennia.contrib.rpg.dice.dice.html | 4 +- .../evennia.contrib.rpg.llm.llm_client.html | 4 +- .../api/evennia.contrib.rpg.llm.llm_npc.html | 12 +++ ...evennia.contrib.rpg.rpsystem.rpsystem.html | 4 +- ...utorials.evadventure.combat_turnbased.html | 4 +- ...b.tutorials.evadventure.combat_twitch.html | 8 +- ...ontrib.tutorials.evadventure.commands.html | 4 +- ...ntrib.tutorials.red_button.red_button.html | 4 +- ...trib.tutorials.tutorial_world.objects.html | 12 +-- ...ontrib.tutorials.tutorial_world.rooms.html | 12 +-- ...utils.git_integration.git_integration.html | 4 +- docs/2.x/api/evennia.utils.eveditor.html | 4 +- docs/2.x/api/evennia.utils.evmenu.html | 4 +- docs/2.x/api/evennia.utils.evmore.html | 4 +- docs/2.x/genindex.html | 4 + docs/2.x/objects.inv | Bin 164295 -> 164307 bytes docs/2.x/searchindex.js | 2 +- 41 files changed, 199 insertions(+), 130 deletions(-) diff --git a/docs/2.x/.buildinfo b/docs/2.x/.buildinfo index b80ad33067..8ee224a920 100644 --- a/docs/2.x/.buildinfo +++ b/docs/2.x/.buildinfo @@ -1,4 +1,4 @@ # Sphinx build info version 1 # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. -config: 356e50c914680767960da44ff30f7f35 +config: cf544763966d9ef752a7041289a667c2 tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs/2.x/Contribs/Contrib-Llm.html b/docs/2.x/Contribs/Contrib-Llm.html index 96789378f0..342c9ed402 100644 --- a/docs/2.x/Contribs/Contrib-Llm.html +++ b/docs/2.x/Contribs/Contrib-Llm.html @@ -152,7 +152,7 @@ villager says (to You): Yeah, it is really quite nice, ain't it.
  • Once all is loaded, stop the server with Ctrl-C (or Cmd-C) and open the file webui.py (it’s one of the top files in the archive you unzipped). Find the text string CMD_FLAGS = '' near the top and change this to CMD_FLAGS = '--api'. Then save and close. This makes the server activate its api automatically.

  • Now just run that server starting script (start_linux.sh etc) again. This is what you’ll use to start the LLM server henceforth.

  • Once the server is running, point your browser to http://127.0.0.1:7860 to see the running Text generation web ui running. If you turned on the API, you’ll find it’s now active on port 5000. This should not collide with default Evennia ports unless you changed something.

  • -
  • At this point you have the server and API, but it’s not actually running any Large-Language-Model (LLM) yet. In the web ui, go to the models tab and enter a github-style path in the Download custom model or LoRA field. To test so things work, enter facebook/opt-125m and download. This is a relatively small model (125 million parameters) so should be possible to run on most machines using only CPU. Update the models in the drop-down on the left and select it, then load it with the Transformers loader. It should load pretty quickly. If you want to load this every time, you can select the Autoload the model checkbox; otherwise you’ll need to select and load the model every time you start the LLM server.

  • +
  • At this point you have the server and API, but it’s not actually running any Large-Language-Model (LLM) yet. In the web ui, go to the models tab and enter a github-style path in the Download custom model or LoRA field. To test so things work, enter DeepPavlov/bart-base-en-persona-chat and download. This is a relatively small model (350 million parameters) so should be possible to run on most machines using only CPU. Update the models in the drop-down on the left and select it, then load it with the Transformers loader. It should load pretty quickly. If you want to load this every time, you can select the Autoload the model checkbox; otherwise you’ll need to select and load the model every time you start the LLM server.

  • To experiment, you can find thousands of other open-source text-generation LLM models on huggingface.co/models. Beware to not download a too huge model; your machine may not be able to load it! If you try large models, don’t set the Autoload the model checkbox, in case the model crashes your server on startup.

  • For troubleshooting, you can look at the terminal output of the text-generation-webui server; it will show you the requests you do to it and also list any errors. See the text-generation-webui homepage for more details.

    @@ -229,6 +229,8 @@ girl says (to You): Hello! How are you?

    The LLMNPC class

    This is a simple Character class, with a few extra properties:

        # response template on msg_contents form.
    +    prompt_prefix = ("You will chat and roleplay ")
    +
         response_template = "$You() $conj(say) (to $You(character)): {response}"
         thinking_timeout = 2    # how long to wait until showing thinking
     
    diff --git a/docs/2.x/_modules/evennia/contrib/rpg/llm/llm_client.html b/docs/2.x/_modules/evennia/contrib/rpg/llm/llm_client.html
    index 9254bf6a54..d1b8717c18 100644
    --- a/docs/2.x/_modules/evennia/contrib/rpg/llm/llm_client.html
    +++ b/docs/2.x/_modules/evennia/contrib/rpg/llm/llm_client.html
    @@ -112,6 +112,7 @@
     
     from django.conf import settings
     from evennia import logger
    +from evennia.utils.utils import make_iter
     from twisted.internet import defer, protocol, reactor
     from twisted.internet.defer import inlineCallbacks
     from twisted.web.client import Agent, HTTPConnectionPool, _HTTP11ClientFactory
    @@ -123,6 +124,7 @@
     DEFAULT_LLM_PATH = "/api/v1/generate"
     DEFAULT_LLM_HEADERS = {"Content-Type": "application/json"}
     DEFAULT_LLM_PROMPT_KEYNAME = "prompt"
    +DEFAULT_LLM_API_TYPE = ""  # or openai
     DEFAULT_LLM_REQUEST_BODY = {
         "max_new_tokens": 250,  # max number of tokens to generate
         "temperature": 0.7,  # higher = more random, lower = more predictable
    @@ -189,7 +191,46 @@
             self.hostname = getattr(settings, "LLM_HOST", DEFAULT_LLM_HOST)
             self.pathname = getattr(settings, "LLM_PATH", DEFAULT_LLM_PATH)
             self.headers = getattr(settings, "LLM_HEADERS", DEFAULT_LLM_HEADERS)
    -        self.request_body = getattr(settings, "LLM_REQUEST_BODY", DEFAULT_LLM_REQUEST_BODY)
    + self.request_body = getattr(settings, "LLM_REQUEST_BODY", DEFAULT_LLM_REQUEST_BODY) + + self.api_type = getattr(settings, "LLM_API_TYPE", DEFAULT_LLM_API_TYPE) + + self.agent = Agent(reactor, pool=self._conn_pool)
    + + def _format_request_body(self, prompt): + """Structure the request body for the LLM server""" + request_body = self.request_body.copy() + + prompt = "\n".join(make_iter(prompt)) + + request_body[self.prompt_keyname] = prompt + + return request_body + + def _handle_llm_response_body(self, response): + """Get the response body from the response""" + d = defer.Deferred() + response.deliverBody(SimpleResponseReceiver(response.code, d)) + return d + + def _handle_llm_error(self, failure): + """Correctly handle server connection errors""" + failure.trap(Exception) + return (500, failure.getErrorMessage()) + + def _get_response_from_llm_server(self, prompt): + """Call the LLM server and handle the response/failure""" + request_body = self._format_request_body(prompt) + + d = self.agent.request( + b"POST", + bytes(self.hostname + self.pathname, "utf-8"), + headers=Headers(self.headers), + bodyProducer=StringProducer(json.dumps(request_body)), + ) + + d.addCallbacks(self._handle_llm_response_body, self._handle_llm_error) + return d
    [docs] @inlineCallbacks def get_response(self, prompt): @@ -197,7 +238,9 @@ Get a response from the LLM server for the given npc. Args: - prompt (str): The prompt to send to the LLM server. + prompt (str or list): The prompt to send to the LLM server. If a list, + this is assumed to be the chat history so far, and will be added to the + prompt in a way suitable for the api. Returns: str: The generated text response. Will return an empty string @@ -210,35 +253,7 @@ return json.loads(response)["results"][0]["text"] else: logger.log_err(f"LLM API error (status {status_code}): {response}") - return ""
    - - def _get_response_from_llm_server(self, prompt): - """Call and wait for response from LLM server""" - - agent = Agent(reactor, pool=self._conn_pool) - - request_body = self.request_body.copy() - request_body[self.prompt_keyname] = prompt - - d = agent.request( - b"POST", - bytes(self.hostname + self.pathname, "utf-8"), - headers=Headers(self.headers), - bodyProducer=StringProducer(json.dumps(request_body)), - ) - - d.addCallbacks(self._handle_llm_response_body, self._handle_llm_error) - return d - - def _handle_llm_response_body(self, response): - """Get the response body from the response""" - d = defer.Deferred() - response.deliverBody(SimpleResponseReceiver(response.code, d)) - return d - - def _handle_llm_error(self, failure): - failure.trap(Exception) - return (500, failure.getErrorMessage()) + return "" diff --git a/docs/2.x/_modules/evennia/contrib/rpg/llm/llm_npc.html b/docs/2.x/_modules/evennia/contrib/rpg/llm/llm_npc.html index 732aeefa24..c48da409a7 100644 --- a/docs/2.x/_modules/evennia/contrib/rpg/llm/llm_npc.html +++ b/docs/2.x/_modules/evennia/contrib/rpg/llm/llm_npc.html @@ -98,6 +98,7 @@ from random import choice +from django.conf import settings from evennia import Command, DefaultCharacter from evennia.utils.utils import make_iter from twisted.internet import reactor, task @@ -105,11 +106,21 @@ from .llm_client import LLMClient +# fallback if not specified anywhere else. Check order is +# npc.db.prompt_prefix, npcClass.prompt_prefix, then settings.LLM_PROMPT_PREFIX, then this +DEFAULT_PROMPT_PREFIX = ( + "You are roleplaying that your name is {name}, a {desc} existing in {location}. " + "Roleplay a suitable response to the following input only: " +) +
    [docs]class LLMNPC(DefaultCharacter): """An NPC that uses the LLM server to generate its responses. If the server is slow, it will echo a thinking message to the character while it waits for a response.""" + # use this to override the prefix per class + prompt_prefix = None + response_template = "$You() $conj(say) (to $You(character)): {response}" thinking_timeout = 2 # seconds thinking_messages = [ @@ -121,8 +132,19 @@ @property def llm_client(self): if not hasattr(self, "_llm_client"): - self._llm_client = LLMClient() - return self._llm_client + self.ndb.llm_client = LLMClient() + return self.ndb.llm_client + + @property + def llm_prompt_prefix(self): + """get prefix, first from Attribute, then from class variable, + then from settings, then from default""" + return self.attributes.get( + "prompt_prefix", + default=getattr( + settings, "LLM_PROMPT_PREFIX", self.prompt_prefix or DEFAULT_PROMPT_PREFIX + ), + )
    [docs] @inlineCallbacks def at_talked_to(self, speech, character): @@ -163,8 +185,18 @@ # if response takes too long, note that the NPC is thinking. thinking_defer = task.deferLater(reactor, self.thinking_timeout, _echo_thinking_message) + prompt = ( + self.llm_prompt_prefix.format( + name=self.key, + desc=self.db.desc or "commoner", + location=self.location.key if self.location else "the void", + ) + + " " + + speech + ) + # get the response from the LLM server - yield self.llm_client.get_response(speech).addCallback(_respond)
    + yield self.llm_client.get_response(prompt).addCallback(_respond)
    [docs]class CmdLLMTalk(Command): diff --git a/docs/2.x/_sources/Contribs/Contrib-Llm.md.txt b/docs/2.x/_sources/Contribs/Contrib-Llm.md.txt index e49d4af9f4..a05d7cc7bf 100644 --- a/docs/2.x/_sources/Contribs/Contrib-Llm.md.txt +++ b/docs/2.x/_sources/Contribs/Contrib-Llm.md.txt @@ -31,7 +31,7 @@ There are many LLM servers, but they can be pretty technical to install and set 4. Once all is loaded, stop the server with `Ctrl-C` (or `Cmd-C`) and open the file `webui.py` (it's one of the top files in the archive you unzipped). Find the text string `CMD_FLAGS = ''` near the top and change this to `CMD_FLAGS = '--api'`. Then save and close. This makes the server activate its api automatically. 4. Now just run that server starting script (`start_linux.sh` etc) again. This is what you'll use to start the LLM server henceforth. 5. Once the server is running, point your browser to http://127.0.0.1:7860 to see the running Text generation web ui running. If you turned on the API, you'll find it's now active on port 5000. This should not collide with default Evennia ports unless you changed something. -6. At this point you have the server and API, but it's not actually running any Large-Language-Model (LLM) yet. In the web ui, go to the `models` tab and enter a github-style path in the `Download custom model or LoRA` field. To test so things work, enter `facebook/opt-125m` and download. This is a relatively small model (125 million parameters) so should be possible to run on most machines using only CPU. Update the models in the drop-down on the left and select it, then load it with the `Transformers` loader. It should load pretty quickly. If you want to load this every time, you can select the `Autoload the model` checkbox; otherwise you'll need to select and load the model every time you start the LLM server. +6. At this point you have the server and API, but it's not actually running any Large-Language-Model (LLM) yet. In the web ui, go to the `models` tab and enter a github-style path in the `Download custom model or LoRA` field. To test so things work, enter `DeepPavlov/bart-base-en-persona-chat` and download. This is a relatively small model (350 million parameters) so should be possible to run on most machines using only CPU. Update the models in the drop-down on the left and select it, then load it with the `Transformers` loader. It should load pretty quickly. If you want to load this every time, you can select the `Autoload the model` checkbox; otherwise you'll need to select and load the model every time you start the LLM server. 7. To experiment, you can find thousands of other open-source text-generation LLM models on [huggingface.co/models](https://huggingface.co/models?pipeline_tag=text-generation&sort=trending). Beware to not download a too huge model; your machine may not be able to load it! If you try large models, _don't_ set the `Autoload the model` checkbox, in case the model crashes your server on startup. For troubleshooting, you can look at the terminal output of the `text-generation-webui` server; it will show you the requests you do to it and also list any errors. See the text-generation-webui homepage for more details. @@ -119,6 +119,8 @@ This is a simple Character class, with a few extra properties: ```python # response template on msg_contents form. + prompt_prefix = ("You will chat and roleplay ") + response_template = "$You() $conj(say) (to $You(character)): {response}" thinking_timeout = 2 # how long to wait until showing thinking diff --git a/docs/2.x/api/evennia.commands.default.account.html b/docs/2.x/api/evennia.commands.default.account.html index cc34d4484b..af4cefee04 100644 --- a/docs/2.x/api/evennia.commands.default.account.html +++ b/docs/2.x/api/evennia.commands.default.account.html @@ -141,7 +141,7 @@ method. Otherwise all text will be returned to all connected sessions.

    -aliases = ['ls', 'l']
    +aliases = ['l', 'ls']
    @@ -172,7 +172,7 @@ method. Otherwise all text will be returned to all connected sessions.

    -search_index_entry = {'aliases': 'ls l', 'category': 'general', 'key': 'look', 'no_prefix': ' ls l', 'tags': '', 'text': '\n look while out-of-character\n\n Usage:\n look\n\n Look in the ooc state.\n '}
    +search_index_entry = {'aliases': 'l ls', 'category': 'general', 'key': 'look', 'no_prefix': ' l ls', 'tags': '', 'text': '\n look while out-of-character\n\n Usage:\n look\n\n Look in the ooc state.\n '}
    diff --git a/docs/2.x/api/evennia.commands.default.building.html b/docs/2.x/api/evennia.commands.default.building.html index 38661cef54..9298a19fd2 100644 --- a/docs/2.x/api/evennia.commands.default.building.html +++ b/docs/2.x/api/evennia.commands.default.building.html @@ -1353,7 +1353,7 @@ server settings.

    -aliases = ['@swap', '@update', '@type', '@parent', '@typeclasses']
    +aliases = ['@typeclasses', '@update', '@parent', '@swap', '@type']
    @@ -1384,7 +1384,7 @@ server settings.

    -search_index_entry = {'aliases': '@swap @update @type @parent @typeclasses', 'category': 'building', 'key': '@typeclass', 'no_prefix': 'typeclass swap update type parent typeclasses', 'tags': '', 'text': "\n set or change an object's typeclass\n\n Usage:\n typeclass[/switch] <object> [= typeclass.path]\n typeclass/prototype <object> = prototype_key\n\n typeclasses or typeclass/list/show [typeclass.path]\n swap - this is a shorthand for using /force/reset flags.\n update - this is a shorthand for using the /force/reload flag.\n\n Switch:\n show, examine - display the current typeclass of object (default) or, if\n given a typeclass path, show the docstring of that typeclass.\n update - *only* re-run at_object_creation on this object\n meaning locks or other properties set later may remain.\n reset - clean out *all* the attributes and properties on the\n object - basically making this a new clean object. This will also\n reset cmdsets!\n force - change to the typeclass also if the object\n already has a typeclass of the same name.\n list - show available typeclasses. Only typeclasses in modules actually\n imported or used from somewhere in the code will show up here\n (those typeclasses are still available if you know the path)\n prototype - clean and overwrite the object with the specified\n prototype key - effectively making a whole new object.\n\n Example:\n type button = examples.red_button.RedButton\n type/prototype button=a red button\n\n If the typeclass_path is not given, the current object's typeclass is\n assumed.\n\n View or set an object's typeclass. If setting, the creation hooks of the\n new typeclass will be run on the object. If you have clashing properties on\n the old class, use /reset. By default you are protected from changing to a\n typeclass of the same name as the one you already have - use /force to\n override this protection.\n\n The given typeclass must be identified by its location using python\n dot-notation pointing to the correct module and class. If no typeclass is\n given (or a wrong typeclass is given). Errors in the path or new typeclass\n will lead to the old typeclass being kept. The location of the typeclass\n module is searched from the default typeclass directory, as defined in the\n server settings.\n\n "}
    +search_index_entry = {'aliases': '@typeclasses @update @parent @swap @type', 'category': 'building', 'key': '@typeclass', 'no_prefix': 'typeclass typeclasses update parent swap type', 'tags': '', 'text': "\n set or change an object's typeclass\n\n Usage:\n typeclass[/switch] <object> [= typeclass.path]\n typeclass/prototype <object> = prototype_key\n\n typeclasses or typeclass/list/show [typeclass.path]\n swap - this is a shorthand for using /force/reset flags.\n update - this is a shorthand for using the /force/reload flag.\n\n Switch:\n show, examine - display the current typeclass of object (default) or, if\n given a typeclass path, show the docstring of that typeclass.\n update - *only* re-run at_object_creation on this object\n meaning locks or other properties set later may remain.\n reset - clean out *all* the attributes and properties on the\n object - basically making this a new clean object. This will also\n reset cmdsets!\n force - change to the typeclass also if the object\n already has a typeclass of the same name.\n list - show available typeclasses. Only typeclasses in modules actually\n imported or used from somewhere in the code will show up here\n (those typeclasses are still available if you know the path)\n prototype - clean and overwrite the object with the specified\n prototype key - effectively making a whole new object.\n\n Example:\n type button = examples.red_button.RedButton\n type/prototype button=a red button\n\n If the typeclass_path is not given, the current object's typeclass is\n assumed.\n\n View or set an object's typeclass. If setting, the creation hooks of the\n new typeclass will be run on the object. If you have clashing properties on\n the old class, use /reset. By default you are protected from changing to a\n typeclass of the same name as the one you already have - use /force to\n override this protection.\n\n The given typeclass must be identified by its location using python\n dot-notation pointing to the correct module and class. If no typeclass is\n given (or a wrong typeclass is given). Errors in the path or new typeclass\n will lead to the old typeclass being kept. The location of the typeclass\n module is searched from the default typeclass directory, as defined in the\n server settings.\n\n "}
    diff --git a/docs/2.x/api/evennia.commands.default.comms.html b/docs/2.x/api/evennia.commands.default.comms.html index 5de183adbf..bc71ab84a5 100644 --- a/docs/2.x/api/evennia.commands.default.comms.html +++ b/docs/2.x/api/evennia.commands.default.comms.html @@ -264,7 +264,7 @@ ban mychannel1,mychannel2= EvilUser : Was banned for spamming.

    -aliases = ['@chan', '@channels']
    +aliases = ['@channels', '@chan']
    @@ -789,7 +789,7 @@ don’t actually sub to yet.

    -search_index_entry = {'aliases': '@chan @channels', 'category': 'comms', 'key': '@channel', 'no_prefix': 'channel chan channels', 'tags': '', 'text': "\n Use and manage in-game channels.\n\n Usage:\n channel channelname <msg>\n channel channel name = <msg>\n channel (show all subscription)\n channel/all (show available channels)\n channel/alias channelname = alias[;alias...]\n channel/unalias alias\n channel/who channelname\n channel/history channelname [= index]\n channel/sub channelname [= alias[;alias...]]\n channel/unsub channelname[,channelname, ...]\n channel/mute channelname[,channelname,...]\n channel/unmute channelname[,channelname,...]\n\n channel/create channelname[;alias;alias[:typeclass]] [= description]\n channel/destroy channelname [= reason]\n channel/desc channelname = description\n channel/lock channelname = lockstring\n channel/unlock channelname = lockstring\n channel/ban channelname (list bans)\n channel/ban[/quiet] channelname[, channelname, ...] = subscribername [: reason]\n channel/unban[/quiet] channelname[, channelname, ...] = subscribername\n channel/boot[/quiet] channelname[,channelname,...] = subscribername [: reason]\n\n # subtopics\n\n ## sending\n\n Usage: channel channelname msg\n channel channel name = msg (with space in channel name)\n\n This sends a message to the channel. Note that you will rarely use this\n command like this; instead you can use the alias\n\n channelname <msg>\n channelalias <msg>\n\n For example\n\n public Hello World\n pub Hello World\n\n (this shortcut doesn't work for aliases containing spaces)\n\n See channel/alias for help on setting channel aliases.\n\n ## alias and unalias\n\n Usage: channel/alias channel = alias[;alias[;alias...]]\n channel/unalias alias\n channel - this will list your subs and aliases to each channel\n\n Set one or more personal aliases for referencing a channel. For example:\n\n channel/alias warrior's guild = warrior;wguild;warchannel;warrior guild\n\n You can now send to the channel using all of these:\n\n warrior's guild Hello\n warrior Hello\n wguild Hello\n warchannel Hello\n\n Note that this will not work if the alias has a space in it. So the\n 'warrior guild' alias must be used with the `channel` command:\n\n channel warrior guild = Hello\n\n Channel-aliases can be removed one at a time, using the '/unalias' switch.\n\n ## who\n\n Usage: channel/who channelname\n\n List the channel's subscribers. Shows who are currently offline or are\n muting the channel. Subscribers who are 'muting' will not see messages sent\n to the channel (use channel/mute to mute a channel).\n\n ## history\n\n Usage: channel/history channel [= index]\n\n This will display the last |c20|n lines of channel history. By supplying an\n index number, you will step that many lines back before viewing those 20 lines.\n\n For example:\n\n channel/history public = 35\n\n will go back 35 lines and show the previous 20 lines from that point (so\n lines -35 to -55).\n\n ## sub and unsub\n\n Usage: channel/sub channel [=alias[;alias;...]]\n channel/unsub channel\n\n This subscribes you to a channel and optionally assigns personal shortcuts\n for you to use to send to that channel (see aliases). When you unsub, all\n your personal aliases will also be removed.\n\n ## mute and unmute\n\n Usage: channel/mute channelname\n channel/unmute channelname\n\n Muting silences all output from the channel without actually\n un-subscribing. Other channel members will see that you are muted in the /who\n list. Sending a message to the channel will automatically unmute you.\n\n ## create and destroy\n\n Usage: channel/create channelname[;alias;alias[:typeclass]] [= description]\n channel/destroy channelname [= reason]\n\n Creates a new channel (or destroys one you control). You will automatically\n join the channel you create and everyone will be kicked and loose all aliases\n to a destroyed channel.\n\n ## lock and unlock\n\n Usage: channel/lock channelname = lockstring\n channel/unlock channelname = lockstring\n\n Note: this is an admin command.\n\n A lockstring is on the form locktype:lockfunc(). Channels understand three\n locktypes:\n listen - who may listen or join the channel.\n send - who may send messages to the channel\n control - who controls the channel. This is usually the one creating\n the channel.\n\n Common lockfuncs are all() and perm(). To make a channel everyone can\n listen to but only builders can talk on, use this:\n\n listen:all()\n send: perm(Builders)\n\n ## boot and ban\n\n Usage:\n channel/boot[/quiet] channelname[,channelname,...] = subscribername [: reason]\n channel/ban channelname[, channelname, ...] = subscribername [: reason]\n channel/unban channelname[, channelname, ...] = subscribername\n channel/unban channelname\n channel/ban channelname (list bans)\n\n Booting will kick a named subscriber from channel(s) temporarily. The\n 'reason' will be passed to the booted user. Unless the /quiet switch is\n used, the channel will also be informed of the action. A booted user is\n still able to re-connect, but they'll have to set up their aliases again.\n\n Banning will blacklist a user from (re)joining the provided channels. It\n will then proceed to boot them from those channels if they were connected.\n The 'reason' and `/quiet` works the same as for booting.\n\n Example:\n boot mychannel1 = EvilUser : Kicking you to cool down a bit.\n ban mychannel1,mychannel2= EvilUser : Was banned for spamming.\n\n "}
    +search_index_entry = {'aliases': '@channels @chan', 'category': 'comms', 'key': '@channel', 'no_prefix': 'channel channels chan', 'tags': '', 'text': "\n Use and manage in-game channels.\n\n Usage:\n channel channelname <msg>\n channel channel name = <msg>\n channel (show all subscription)\n channel/all (show available channels)\n channel/alias channelname = alias[;alias...]\n channel/unalias alias\n channel/who channelname\n channel/history channelname [= index]\n channel/sub channelname [= alias[;alias...]]\n channel/unsub channelname[,channelname, ...]\n channel/mute channelname[,channelname,...]\n channel/unmute channelname[,channelname,...]\n\n channel/create channelname[;alias;alias[:typeclass]] [= description]\n channel/destroy channelname [= reason]\n channel/desc channelname = description\n channel/lock channelname = lockstring\n channel/unlock channelname = lockstring\n channel/ban channelname (list bans)\n channel/ban[/quiet] channelname[, channelname, ...] = subscribername [: reason]\n channel/unban[/quiet] channelname[, channelname, ...] = subscribername\n channel/boot[/quiet] channelname[,channelname,...] = subscribername [: reason]\n\n # subtopics\n\n ## sending\n\n Usage: channel channelname msg\n channel channel name = msg (with space in channel name)\n\n This sends a message to the channel. Note that you will rarely use this\n command like this; instead you can use the alias\n\n channelname <msg>\n channelalias <msg>\n\n For example\n\n public Hello World\n pub Hello World\n\n (this shortcut doesn't work for aliases containing spaces)\n\n See channel/alias for help on setting channel aliases.\n\n ## alias and unalias\n\n Usage: channel/alias channel = alias[;alias[;alias...]]\n channel/unalias alias\n channel - this will list your subs and aliases to each channel\n\n Set one or more personal aliases for referencing a channel. For example:\n\n channel/alias warrior's guild = warrior;wguild;warchannel;warrior guild\n\n You can now send to the channel using all of these:\n\n warrior's guild Hello\n warrior Hello\n wguild Hello\n warchannel Hello\n\n Note that this will not work if the alias has a space in it. So the\n 'warrior guild' alias must be used with the `channel` command:\n\n channel warrior guild = Hello\n\n Channel-aliases can be removed one at a time, using the '/unalias' switch.\n\n ## who\n\n Usage: channel/who channelname\n\n List the channel's subscribers. Shows who are currently offline or are\n muting the channel. Subscribers who are 'muting' will not see messages sent\n to the channel (use channel/mute to mute a channel).\n\n ## history\n\n Usage: channel/history channel [= index]\n\n This will display the last |c20|n lines of channel history. By supplying an\n index number, you will step that many lines back before viewing those 20 lines.\n\n For example:\n\n channel/history public = 35\n\n will go back 35 lines and show the previous 20 lines from that point (so\n lines -35 to -55).\n\n ## sub and unsub\n\n Usage: channel/sub channel [=alias[;alias;...]]\n channel/unsub channel\n\n This subscribes you to a channel and optionally assigns personal shortcuts\n for you to use to send to that channel (see aliases). When you unsub, all\n your personal aliases will also be removed.\n\n ## mute and unmute\n\n Usage: channel/mute channelname\n channel/unmute channelname\n\n Muting silences all output from the channel without actually\n un-subscribing. Other channel members will see that you are muted in the /who\n list. Sending a message to the channel will automatically unmute you.\n\n ## create and destroy\n\n Usage: channel/create channelname[;alias;alias[:typeclass]] [= description]\n channel/destroy channelname [= reason]\n\n Creates a new channel (or destroys one you control). You will automatically\n join the channel you create and everyone will be kicked and loose all aliases\n to a destroyed channel.\n\n ## lock and unlock\n\n Usage: channel/lock channelname = lockstring\n channel/unlock channelname = lockstring\n\n Note: this is an admin command.\n\n A lockstring is on the form locktype:lockfunc(). Channels understand three\n locktypes:\n listen - who may listen or join the channel.\n send - who may send messages to the channel\n control - who controls the channel. This is usually the one creating\n the channel.\n\n Common lockfuncs are all() and perm(). To make a channel everyone can\n listen to but only builders can talk on, use this:\n\n listen:all()\n send: perm(Builders)\n\n ## boot and ban\n\n Usage:\n channel/boot[/quiet] channelname[,channelname,...] = subscribername [: reason]\n channel/ban channelname[, channelname, ...] = subscribername [: reason]\n channel/unban channelname[, channelname, ...] = subscribername\n channel/unban channelname\n channel/ban channelname (list bans)\n\n Booting will kick a named subscriber from channel(s) temporarily. The\n 'reason' will be passed to the booted user. Unless the /quiet switch is\n used, the channel will also be informed of the action. A booted user is\n still able to re-connect, but they'll have to set up their aliases again.\n\n Banning will blacklist a user from (re)joining the provided channels. It\n will then proceed to boot them from those channels if they were connected.\n The 'reason' and `/quiet` works the same as for booting.\n\n Example:\n boot mychannel1 = EvilUser : Kicking you to cool down a bit.\n ban mychannel1,mychannel2= EvilUser : Was banned for spamming.\n\n "}
    @@ -942,7 +942,7 @@ ban mychannel1,mychannel2= EvilUser : Was banned for spamming.

    -aliases = ['@chan', '@channels']
    +aliases = ['@channels', '@chan']
    @@ -962,7 +962,7 @@ ban mychannel1,mychannel2= EvilUser : Was banned for spamming.

    -search_index_entry = {'aliases': '@chan @channels', 'category': 'comms', 'key': '@channel', 'no_prefix': 'channel chan channels', 'tags': '', 'text': "\n Use and manage in-game channels.\n\n Usage:\n channel channelname <msg>\n channel channel name = <msg>\n channel (show all subscription)\n channel/all (show available channels)\n channel/alias channelname = alias[;alias...]\n channel/unalias alias\n channel/who channelname\n channel/history channelname [= index]\n channel/sub channelname [= alias[;alias...]]\n channel/unsub channelname[,channelname, ...]\n channel/mute channelname[,channelname,...]\n channel/unmute channelname[,channelname,...]\n\n channel/create channelname[;alias;alias[:typeclass]] [= description]\n channel/destroy channelname [= reason]\n channel/desc channelname = description\n channel/lock channelname = lockstring\n channel/unlock channelname = lockstring\n channel/ban channelname (list bans)\n channel/ban[/quiet] channelname[, channelname, ...] = subscribername [: reason]\n channel/unban[/quiet] channelname[, channelname, ...] = subscribername\n channel/boot[/quiet] channelname[,channelname,...] = subscribername [: reason]\n\n # subtopics\n\n ## sending\n\n Usage: channel channelname msg\n channel channel name = msg (with space in channel name)\n\n This sends a message to the channel. Note that you will rarely use this\n command like this; instead you can use the alias\n\n channelname <msg>\n channelalias <msg>\n\n For example\n\n public Hello World\n pub Hello World\n\n (this shortcut doesn't work for aliases containing spaces)\n\n See channel/alias for help on setting channel aliases.\n\n ## alias and unalias\n\n Usage: channel/alias channel = alias[;alias[;alias...]]\n channel/unalias alias\n channel - this will list your subs and aliases to each channel\n\n Set one or more personal aliases for referencing a channel. For example:\n\n channel/alias warrior's guild = warrior;wguild;warchannel;warrior guild\n\n You can now send to the channel using all of these:\n\n warrior's guild Hello\n warrior Hello\n wguild Hello\n warchannel Hello\n\n Note that this will not work if the alias has a space in it. So the\n 'warrior guild' alias must be used with the `channel` command:\n\n channel warrior guild = Hello\n\n Channel-aliases can be removed one at a time, using the '/unalias' switch.\n\n ## who\n\n Usage: channel/who channelname\n\n List the channel's subscribers. Shows who are currently offline or are\n muting the channel. Subscribers who are 'muting' will not see messages sent\n to the channel (use channel/mute to mute a channel).\n\n ## history\n\n Usage: channel/history channel [= index]\n\n This will display the last |c20|n lines of channel history. By supplying an\n index number, you will step that many lines back before viewing those 20 lines.\n\n For example:\n\n channel/history public = 35\n\n will go back 35 lines and show the previous 20 lines from that point (so\n lines -35 to -55).\n\n ## sub and unsub\n\n Usage: channel/sub channel [=alias[;alias;...]]\n channel/unsub channel\n\n This subscribes you to a channel and optionally assigns personal shortcuts\n for you to use to send to that channel (see aliases). When you unsub, all\n your personal aliases will also be removed.\n\n ## mute and unmute\n\n Usage: channel/mute channelname\n channel/unmute channelname\n\n Muting silences all output from the channel without actually\n un-subscribing. Other channel members will see that you are muted in the /who\n list. Sending a message to the channel will automatically unmute you.\n\n ## create and destroy\n\n Usage: channel/create channelname[;alias;alias[:typeclass]] [= description]\n channel/destroy channelname [= reason]\n\n Creates a new channel (or destroys one you control). You will automatically\n join the channel you create and everyone will be kicked and loose all aliases\n to a destroyed channel.\n\n ## lock and unlock\n\n Usage: channel/lock channelname = lockstring\n channel/unlock channelname = lockstring\n\n Note: this is an admin command.\n\n A lockstring is on the form locktype:lockfunc(). Channels understand three\n locktypes:\n listen - who may listen or join the channel.\n send - who may send messages to the channel\n control - who controls the channel. This is usually the one creating\n the channel.\n\n Common lockfuncs are all() and perm(). To make a channel everyone can\n listen to but only builders can talk on, use this:\n\n listen:all()\n send: perm(Builders)\n\n ## boot and ban\n\n Usage:\n channel/boot[/quiet] channelname[,channelname,...] = subscribername [: reason]\n channel/ban channelname[, channelname, ...] = subscribername [: reason]\n channel/unban channelname[, channelname, ...] = subscribername\n channel/unban channelname\n channel/ban channelname (list bans)\n\n Booting will kick a named subscriber from channel(s) temporarily. The\n 'reason' will be passed to the booted user. Unless the /quiet switch is\n used, the channel will also be informed of the action. A booted user is\n still able to re-connect, but they'll have to set up their aliases again.\n\n Banning will blacklist a user from (re)joining the provided channels. It\n will then proceed to boot them from those channels if they were connected.\n The 'reason' and `/quiet` works the same as for booting.\n\n Example:\n boot mychannel1 = EvilUser : Kicking you to cool down a bit.\n ban mychannel1,mychannel2= EvilUser : Was banned for spamming.\n\n "}
    +search_index_entry = {'aliases': '@channels @chan', 'category': 'comms', 'key': '@channel', 'no_prefix': 'channel channels chan', 'tags': '', 'text': "\n Use and manage in-game channels.\n\n Usage:\n channel channelname <msg>\n channel channel name = <msg>\n channel (show all subscription)\n channel/all (show available channels)\n channel/alias channelname = alias[;alias...]\n channel/unalias alias\n channel/who channelname\n channel/history channelname [= index]\n channel/sub channelname [= alias[;alias...]]\n channel/unsub channelname[,channelname, ...]\n channel/mute channelname[,channelname,...]\n channel/unmute channelname[,channelname,...]\n\n channel/create channelname[;alias;alias[:typeclass]] [= description]\n channel/destroy channelname [= reason]\n channel/desc channelname = description\n channel/lock channelname = lockstring\n channel/unlock channelname = lockstring\n channel/ban channelname (list bans)\n channel/ban[/quiet] channelname[, channelname, ...] = subscribername [: reason]\n channel/unban[/quiet] channelname[, channelname, ...] = subscribername\n channel/boot[/quiet] channelname[,channelname,...] = subscribername [: reason]\n\n # subtopics\n\n ## sending\n\n Usage: channel channelname msg\n channel channel name = msg (with space in channel name)\n\n This sends a message to the channel. Note that you will rarely use this\n command like this; instead you can use the alias\n\n channelname <msg>\n channelalias <msg>\n\n For example\n\n public Hello World\n pub Hello World\n\n (this shortcut doesn't work for aliases containing spaces)\n\n See channel/alias for help on setting channel aliases.\n\n ## alias and unalias\n\n Usage: channel/alias channel = alias[;alias[;alias...]]\n channel/unalias alias\n channel - this will list your subs and aliases to each channel\n\n Set one or more personal aliases for referencing a channel. For example:\n\n channel/alias warrior's guild = warrior;wguild;warchannel;warrior guild\n\n You can now send to the channel using all of these:\n\n warrior's guild Hello\n warrior Hello\n wguild Hello\n warchannel Hello\n\n Note that this will not work if the alias has a space in it. So the\n 'warrior guild' alias must be used with the `channel` command:\n\n channel warrior guild = Hello\n\n Channel-aliases can be removed one at a time, using the '/unalias' switch.\n\n ## who\n\n Usage: channel/who channelname\n\n List the channel's subscribers. Shows who are currently offline or are\n muting the channel. Subscribers who are 'muting' will not see messages sent\n to the channel (use channel/mute to mute a channel).\n\n ## history\n\n Usage: channel/history channel [= index]\n\n This will display the last |c20|n lines of channel history. By supplying an\n index number, you will step that many lines back before viewing those 20 lines.\n\n For example:\n\n channel/history public = 35\n\n will go back 35 lines and show the previous 20 lines from that point (so\n lines -35 to -55).\n\n ## sub and unsub\n\n Usage: channel/sub channel [=alias[;alias;...]]\n channel/unsub channel\n\n This subscribes you to a channel and optionally assigns personal shortcuts\n for you to use to send to that channel (see aliases). When you unsub, all\n your personal aliases will also be removed.\n\n ## mute and unmute\n\n Usage: channel/mute channelname\n channel/unmute channelname\n\n Muting silences all output from the channel without actually\n un-subscribing. Other channel members will see that you are muted in the /who\n list. Sending a message to the channel will automatically unmute you.\n\n ## create and destroy\n\n Usage: channel/create channelname[;alias;alias[:typeclass]] [= description]\n channel/destroy channelname [= reason]\n\n Creates a new channel (or destroys one you control). You will automatically\n join the channel you create and everyone will be kicked and loose all aliases\n to a destroyed channel.\n\n ## lock and unlock\n\n Usage: channel/lock channelname = lockstring\n channel/unlock channelname = lockstring\n\n Note: this is an admin command.\n\n A lockstring is on the form locktype:lockfunc(). Channels understand three\n locktypes:\n listen - who may listen or join the channel.\n send - who may send messages to the channel\n control - who controls the channel. This is usually the one creating\n the channel.\n\n Common lockfuncs are all() and perm(). To make a channel everyone can\n listen to but only builders can talk on, use this:\n\n listen:all()\n send: perm(Builders)\n\n ## boot and ban\n\n Usage:\n channel/boot[/quiet] channelname[,channelname,...] = subscribername [: reason]\n channel/ban channelname[, channelname, ...] = subscribername [: reason]\n channel/unban channelname[, channelname, ...] = subscribername\n channel/unban channelname\n channel/ban channelname (list bans)\n\n Booting will kick a named subscriber from channel(s) temporarily. The\n 'reason' will be passed to the booted user. Unless the /quiet switch is\n used, the channel will also be informed of the action. A booted user is\n still able to re-connect, but they'll have to set up their aliases again.\n\n Banning will blacklist a user from (re)joining the provided channels. It\n will then proceed to boot them from those channels if they were connected.\n The 'reason' and `/quiet` works the same as for booting.\n\n Example:\n boot mychannel1 = EvilUser : Kicking you to cool down a bit.\n ban mychannel1,mychannel2= EvilUser : Was banned for spamming.\n\n "}
    diff --git a/docs/2.x/api/evennia.commands.default.general.html b/docs/2.x/api/evennia.commands.default.general.html index 68149702c1..c0a1f7cb73 100644 --- a/docs/2.x/api/evennia.commands.default.general.html +++ b/docs/2.x/api/evennia.commands.default.general.html @@ -183,7 +183,7 @@ look *<account&g
    -aliases = ['ls', 'l']
    +aliases = ['l', 'ls']
    @@ -214,7 +214,7 @@ look *<account&g
    -search_index_entry = {'aliases': 'ls l', 'category': 'general', 'key': 'look', 'no_prefix': ' ls l', 'tags': '', 'text': '\n look at location or object\n\n Usage:\n look\n look <obj>\n look *<account>\n\n Observes your location or objects in your vicinity.\n '}
    +search_index_entry = {'aliases': 'l ls', 'category': 'general', 'key': 'look', 'no_prefix': ' l ls', 'tags': '', 'text': '\n look at location or object\n\n Usage:\n look\n look <obj>\n look *<account>\n\n Observes your location or objects in your vicinity.\n '}
    @@ -331,7 +331,7 @@ inv

    -aliases = ['i', 'inv']
    +aliases = ['inv', 'i']
    @@ -362,7 +362,7 @@ inv

    -search_index_entry = {'aliases': 'i inv', 'category': 'general', 'key': 'inventory', 'no_prefix': ' i inv', 'tags': '', 'text': '\n view inventory\n\n Usage:\n inventory\n inv\n\n Shows your inventory.\n '}
    +search_index_entry = {'aliases': 'inv i', 'category': 'general', 'key': 'inventory', 'no_prefix': ' inv i', 'tags': '', 'text': '\n view inventory\n\n Usage:\n inventory\n inv\n\n Shows your inventory.\n '}
    @@ -781,7 +781,7 @@ which permission groups you are a member of.

    -aliases = ['groups', 'hierarchy']
    +aliases = ['hierarchy', 'groups']
    @@ -812,7 +812,7 @@ which permission groups you are a member of.

    -search_index_entry = {'aliases': 'groups hierarchy', 'category': 'general', 'key': 'access', 'no_prefix': ' groups hierarchy', 'tags': '', 'text': '\n show your current game access\n\n Usage:\n access\n\n This command shows you the permission hierarchy and\n which permission groups you are a member of.\n '}
    +search_index_entry = {'aliases': 'hierarchy groups', 'category': 'general', 'key': 'access', 'no_prefix': ' hierarchy groups', 'tags': '', 'text': '\n show your current game access\n\n Usage:\n access\n\n This command shows you the permission hierarchy and\n which permission groups you are a member of.\n '}
    diff --git a/docs/2.x/api/evennia.commands.default.system.html b/docs/2.x/api/evennia.commands.default.system.html index dc97c889a1..4f4b66b558 100644 --- a/docs/2.x/api/evennia.commands.default.system.html +++ b/docs/2.x/api/evennia.commands.default.system.html @@ -691,7 +691,7 @@ See |luhttps://ww
    -aliases = ['@task', '@delays']
    +aliases = ['@delays', '@task']
    @@ -737,7 +737,7 @@ to all the variables defined therein.

    -search_index_entry = {'aliases': '@task @delays', 'category': 'system', 'key': '@tasks', 'no_prefix': 'tasks task delays', 'tags': '', 'text': "\n Display or terminate active tasks (delays).\n\n Usage:\n tasks[/switch] [task_id or function_name]\n\n Switches:\n pause - Pause the callback of a task.\n unpause - Process all callbacks made since pause() was called.\n do_task - Execute the task (call its callback).\n call - Call the callback of this task.\n remove - Remove a task without executing it.\n cancel - Stop a task from automatically executing.\n\n Notes:\n A task is a single use method of delaying the call of a function. Calls are created\n in code, using `evennia.utils.delay`.\n See |luhttps://www.evennia.com/docs/latest/Command-Duration.html|ltthe docs|le for help.\n\n By default, tasks that are canceled and never called are cleaned up after one minute.\n\n Examples:\n - `tasks/cancel move_callback` - Cancels all movement delays from the slow_exit contrib.\n In this example slow exits creates it's tasks with\n `utils.delay(move_delay, move_callback)`\n - `tasks/cancel 2` - Cancel task id 2.\n\n "}
    +search_index_entry = {'aliases': '@delays @task', 'category': 'system', 'key': '@tasks', 'no_prefix': 'tasks delays task', 'tags': '', 'text': "\n Display or terminate active tasks (delays).\n\n Usage:\n tasks[/switch] [task_id or function_name]\n\n Switches:\n pause - Pause the callback of a task.\n unpause - Process all callbacks made since pause() was called.\n do_task - Execute the task (call its callback).\n call - Call the callback of this task.\n remove - Remove a task without executing it.\n cancel - Stop a task from automatically executing.\n\n Notes:\n A task is a single use method of delaying the call of a function. Calls are created\n in code, using `evennia.utils.delay`.\n See |luhttps://www.evennia.com/docs/latest/Command-Duration.html|ltthe docs|le for help.\n\n By default, tasks that are canceled and never called are cleaned up after one minute.\n\n Examples:\n - `tasks/cancel move_callback` - Cancels all movement delays from the slow_exit contrib.\n In this example slow exits creates it's tasks with\n `utils.delay(move_delay, move_callback)`\n - `tasks/cancel 2` - Cancel task id 2.\n\n "}
    diff --git a/docs/2.x/api/evennia.commands.default.tests.html b/docs/2.x/api/evennia.commands.default.tests.html index 442b67db34..1d2b1fb2e5 100644 --- a/docs/2.x/api/evennia.commands.default.tests.html +++ b/docs/2.x/api/evennia.commands.default.tests.html @@ -963,7 +963,7 @@ main test suite started with

    Test the batch processor.

    -red_button = <module 'evennia.contrib.tutorials.red_button.red_button' from '/tmp/tmpry4ablff/812642bbfdc6881c208c56ca311807c32b7bba5e/evennia/contrib/tutorials/red_button/red_button.py'>
    +red_button = <module 'evennia.contrib.tutorials.red_button.red_button' from '/tmp/tmpulxo9thq/06fdeabc34bf2e297fef06ae18077fb34993b062/evennia/contrib/tutorials/red_button/red_button.py'>
    diff --git a/docs/2.x/api/evennia.commands.default.unloggedin.html b/docs/2.x/api/evennia.commands.default.unloggedin.html index 85a09ecffe..b596087ec4 100644 --- a/docs/2.x/api/evennia.commands.default.unloggedin.html +++ b/docs/2.x/api/evennia.commands.default.unloggedin.html @@ -189,7 +189,7 @@ create “account name” “pass word”

    -aliases = ['cre', 'cr']
    +aliases = ['cr', 'cre']
    @@ -226,7 +226,7 @@ create “account name” “pass word”

    -search_index_entry = {'aliases': 'cre cr', 'category': 'general', 'key': 'create', 'no_prefix': ' cre cr', 'tags': '', 'text': '\n create a new account account\n\n Usage (at login screen):\n create <accountname> <password>\n create "account name" "pass word"\n\n This creates a new account account.\n\n If you have spaces in your name, enclose it in double quotes.\n '}
    +search_index_entry = {'aliases': 'cr cre', 'category': 'general', 'key': 'create', 'no_prefix': ' cr cre', 'tags': '', 'text': '\n create a new account account\n\n Usage (at login screen):\n create <accountname> <password>\n create "account name" "pass word"\n\n This creates a new account account.\n\n If you have spaces in your name, enclose it in double quotes.\n '}
    @@ -349,7 +349,7 @@ for simplicity. It shows a pane of info.

    -aliases = ['?', 'h']
    +aliases = ['h', '?']
    @@ -375,7 +375,7 @@ for simplicity. It shows a pane of info.

    -search_index_entry = {'aliases': '? h', 'category': 'general', 'key': 'help', 'no_prefix': ' ? h', 'tags': '', 'text': '\n get help when in unconnected-in state\n\n Usage:\n help\n\n This is an unconnected version of the help command,\n for simplicity. It shows a pane of info.\n '}
    +search_index_entry = {'aliases': 'h ?', 'category': 'general', 'key': 'help', 'no_prefix': ' h ?', 'tags': '', 'text': '\n get help when in unconnected-in state\n\n Usage:\n help\n\n This is an unconnected version of the help command,\n for simplicity. It shows a pane of info.\n '}
    diff --git a/docs/2.x/api/evennia.contrib.base_systems.email_login.email_login.html b/docs/2.x/api/evennia.contrib.base_systems.email_login.email_login.html index 34065d9e31..1382632964 100644 --- a/docs/2.x/api/evennia.contrib.base_systems.email_login.email_login.html +++ b/docs/2.x/api/evennia.contrib.base_systems.email_login.email_login.html @@ -199,7 +199,7 @@ there is no object yet before the account has logged in)

    -aliases = ['cre', 'cr']
    +aliases = ['cr', 'cre']
    @@ -235,7 +235,7 @@ name enclosed in quotes:

    -search_index_entry = {'aliases': 'cre cr', 'category': 'general', 'key': 'create', 'no_prefix': ' cre cr', 'tags': '', 'text': '\n Create a new account.\n\n Usage (at login screen):\n create "accountname" <email> <password>\n\n This creates a new account account.\n\n '}
    +search_index_entry = {'aliases': 'cr cre', 'category': 'general', 'key': 'create', 'no_prefix': ' cr cre', 'tags': '', 'text': '\n Create a new account.\n\n Usage (at login screen):\n create "accountname" <email> <password>\n\n This creates a new account account.\n\n '}
    @@ -343,7 +343,7 @@ for simplicity. It shows a pane of info.

    -aliases = ['?', 'h']
    +aliases = ['h', '?']
    @@ -369,7 +369,7 @@ for simplicity. It shows a pane of info.

    -search_index_entry = {'aliases': '? h', 'category': 'general', 'key': 'help', 'no_prefix': ' ? h', 'tags': '', 'text': '\n This is an unconnected version of the help command,\n for simplicity. It shows a pane of info.\n '}
    +search_index_entry = {'aliases': 'h ?', 'category': 'general', 'key': 'help', 'no_prefix': ' h ?', 'tags': '', 'text': '\n This is an unconnected version of the help command,\n for simplicity. It shows a pane of info.\n '}
    diff --git a/docs/2.x/api/evennia.contrib.base_systems.ingame_python.commands.html b/docs/2.x/api/evennia.contrib.base_systems.ingame_python.commands.html index 45e4c64ead..7d5faa367c 100644 --- a/docs/2.x/api/evennia.contrib.base_systems.ingame_python.commands.html +++ b/docs/2.x/api/evennia.contrib.base_systems.ingame_python.commands.html @@ -124,7 +124,7 @@
    -aliases = ['@callbacks', '@calls', '@callback']
    +aliases = ['@callbacks', '@callback', '@calls']
    @@ -205,7 +205,7 @@ on user permission.

    -search_index_entry = {'aliases': '@callbacks @calls @callback', 'category': 'building', 'key': '@call', 'no_prefix': 'call callbacks calls callback', 'tags': '', 'text': '\n Command to edit callbacks.\n '}
    +search_index_entry = {'aliases': '@callbacks @callback @calls', 'category': 'building', 'key': '@call', 'no_prefix': 'call callbacks callback calls', 'tags': '', 'text': '\n Command to edit callbacks.\n '}
    diff --git a/docs/2.x/api/evennia.contrib.base_systems.mux_comms_cmds.mux_comms_cmds.html b/docs/2.x/api/evennia.contrib.base_systems.mux_comms_cmds.mux_comms_cmds.html index 0023bae949..7c888fd333 100644 --- a/docs/2.x/api/evennia.contrib.base_systems.mux_comms_cmds.mux_comms_cmds.html +++ b/docs/2.x/api/evennia.contrib.base_systems.mux_comms_cmds.mux_comms_cmds.html @@ -168,7 +168,7 @@ aliases to an already joined channel.

    -aliases = ['aliaschan', 'chanalias']
    +aliases = ['chanalias', 'aliaschan']
    @@ -199,7 +199,7 @@ aliases to an already joined channel.

    -search_index_entry = {'aliases': 'aliaschan chanalias', 'category': 'comms', 'key': 'addcom', 'no_prefix': ' aliaschan chanalias', 'tags': '', 'text': '\n Add a channel alias and/or subscribe to a channel\n\n Usage:\n addcom [alias=] <channel>\n\n Joins a given channel. If alias is given, this will allow you to\n refer to the channel by this alias rather than the full channel\n name. Subsequent calls of this command can be used to add multiple\n aliases to an already joined channel.\n '}
    +search_index_entry = {'aliases': 'chanalias aliaschan', 'category': 'comms', 'key': 'addcom', 'no_prefix': ' chanalias aliaschan', 'tags': '', 'text': '\n Add a channel alias and/or subscribe to a channel\n\n Usage:\n addcom [alias=] <channel>\n\n Joins a given channel. If alias is given, this will allow you to\n refer to the channel by this alias rather than the full channel\n name. Subsequent calls of this command can be used to add multiple\n aliases to an already joined channel.\n '}
    @@ -225,7 +225,7 @@ for that channel.

    -aliases = ['delaliaschan', 'delchanalias']
    +aliases = ['delchanalias', 'delaliaschan']
    @@ -256,7 +256,7 @@ for that channel.

    -search_index_entry = {'aliases': 'delaliaschan delchanalias', 'category': 'comms', 'key': 'delcom', 'no_prefix': ' delaliaschan delchanalias', 'tags': '', 'text': "\n remove a channel alias and/or unsubscribe from channel\n\n Usage:\n delcom <alias or channel>\n delcom/all <channel>\n\n If the full channel name is given, unsubscribe from the\n channel. If an alias is given, remove the alias but don't\n unsubscribe. If the 'all' switch is used, remove all aliases\n for that channel.\n "}
    +search_index_entry = {'aliases': 'delchanalias delaliaschan', 'category': 'comms', 'key': 'delcom', 'no_prefix': ' delchanalias delaliaschan', 'tags': '', 'text': "\n remove a channel alias and/or unsubscribe from channel\n\n Usage:\n delcom <alias or channel>\n delcom/all <channel>\n\n If the full channel name is given, unsubscribe from the\n channel. If an alias is given, remove the alias but don't\n unsubscribe. If the 'all' switch is used, remove all aliases\n for that channel.\n "}
    diff --git a/docs/2.x/api/evennia.contrib.full_systems.evscaperoom.commands.html b/docs/2.x/api/evennia.contrib.full_systems.evscaperoom.commands.html index a9a66f8a8a..7cf1b82653 100644 --- a/docs/2.x/api/evennia.contrib.full_systems.evscaperoom.commands.html +++ b/docs/2.x/api/evennia.contrib.full_systems.evscaperoom.commands.html @@ -219,7 +219,7 @@ the operation will be general or on the room.

    -aliases = ['quit', 'abort', 'q', 'chicken out']
    +aliases = ['q', 'quit', 'chicken out', 'abort']
    @@ -243,7 +243,7 @@ set in self.parse())

    -search_index_entry = {'aliases': 'quit abort q chicken out', 'category': 'evscaperoom', 'key': 'give up', 'no_prefix': ' quit abort q chicken out', 'tags': '', 'text': '\n Give up\n\n Usage:\n give up\n\n Abandons your attempts at escaping and of ever winning the pie-eating contest.\n\n '}
    +search_index_entry = {'aliases': 'q quit chicken out abort', 'category': 'evscaperoom', 'key': 'give up', 'no_prefix': ' q quit chicken out abort', 'tags': '', 'text': '\n Give up\n\n Usage:\n give up\n\n Abandons your attempts at escaping and of ever winning the pie-eating contest.\n\n '}
    @@ -264,7 +264,7 @@ set in self.parse())

    -aliases = ['ls', 'l']
    +aliases = ['l', 'ls']
    @@ -298,7 +298,7 @@ set in self.parse())

    -search_index_entry = {'aliases': 'ls l', 'category': 'evscaperoom', 'key': 'look', 'no_prefix': ' ls l', 'tags': '', 'text': '\n Look at the room, an object or the currently focused object\n\n Usage:\n look [obj]\n\n '}
    +search_index_entry = {'aliases': 'l ls', 'category': 'evscaperoom', 'key': 'look', 'no_prefix': ' l ls', 'tags': '', 'text': '\n Look at the room, an object or the currently focused object\n\n Usage:\n look [obj]\n\n '}
    @@ -379,7 +379,7 @@ shout

    -aliases = ['whisper', 'shout', ';']
    +aliases = ['whisper', ';', 'shout']
    @@ -408,7 +408,7 @@ set in self.parse())

    -search_index_entry = {'aliases': 'whisper shout ;', 'category': 'general', 'key': 'say', 'no_prefix': ' whisper shout ;', 'tags': '', 'text': '\n Perform an communication action.\n\n Usage:\n say <text>\n whisper\n shout\n\n '}
    +search_index_entry = {'aliases': 'whisper ; shout', 'category': 'general', 'key': 'say', 'no_prefix': ' whisper ; shout', 'tags': '', 'text': '\n Perform an communication action.\n\n Usage:\n say <text>\n whisper\n shout\n\n '}
    @@ -498,7 +498,7 @@ looks and what actions is available.

    -aliases = ['unfocus', 'ex', 'e', 'examine']
    +aliases = ['e', 'examine', 'unfocus', 'ex']
    @@ -527,7 +527,7 @@ set in self.parse())

    -search_index_entry = {'aliases': 'unfocus ex e examine', 'category': 'evscaperoom', 'key': 'focus', 'no_prefix': ' unfocus ex e examine', 'tags': '', 'text': '\n Focus your attention on a target.\n\n Usage:\n focus <obj>\n\n Once focusing on an object, use look to get more information about how it\n looks and what actions is available.\n\n '}
    +search_index_entry = {'aliases': 'e examine unfocus ex', 'category': 'evscaperoom', 'key': 'focus', 'no_prefix': ' e examine unfocus ex', 'tags': '', 'text': '\n Focus your attention on a target.\n\n Usage:\n focus <obj>\n\n Once focusing on an object, use look to get more information about how it\n looks and what actions is available.\n\n '}
    @@ -589,7 +589,7 @@ set in self.parse())

    -aliases = ['inventory', 'i', 'give', 'inv']
    +aliases = ['give', 'inv', 'i', 'inventory']
    @@ -613,7 +613,7 @@ set in self.parse())

    -search_index_entry = {'aliases': 'inventory i give inv', 'category': 'evscaperoom', 'key': 'get', 'no_prefix': ' inventory i give inv', 'tags': '', 'text': '\n Use focus / examine instead.\n\n '}
    +search_index_entry = {'aliases': 'give inv i inventory', 'category': 'evscaperoom', 'key': 'get', 'no_prefix': ' give inv i inventory', 'tags': '', 'text': '\n Use focus / examine instead.\n\n '}
    diff --git a/docs/2.x/api/evennia.contrib.game_systems.clothing.clothing.html b/docs/2.x/api/evennia.contrib.game_systems.clothing.clothing.html index 2c3865a810..7c96a8a017 100644 --- a/docs/2.x/api/evennia.contrib.game_systems.clothing.clothing.html +++ b/docs/2.x/api/evennia.contrib.game_systems.clothing.clothing.html @@ -630,7 +630,7 @@ inv

    -aliases = ['i', 'inv']
    +aliases = ['inv', 'i']
    @@ -661,7 +661,7 @@ inv

    -search_index_entry = {'aliases': 'i inv', 'category': 'general', 'key': 'inventory', 'no_prefix': ' i inv', 'tags': '', 'text': '\n view inventory\n\n Usage:\n inventory\n inv\n\n Shows your inventory.\n '}
    +search_index_entry = {'aliases': 'inv i', 'category': 'general', 'key': 'inventory', 'no_prefix': ' inv i', 'tags': '', 'text': '\n view inventory\n\n Usage:\n inventory\n inv\n\n Shows your inventory.\n '}
    diff --git a/docs/2.x/api/evennia.contrib.game_systems.turnbattle.tb_basic.html b/docs/2.x/api/evennia.contrib.game_systems.turnbattle.tb_basic.html index 740aeb1135..eadd9e7ce4 100644 --- a/docs/2.x/api/evennia.contrib.game_systems.turnbattle.tb_basic.html +++ b/docs/2.x/api/evennia.contrib.game_systems.turnbattle.tb_basic.html @@ -680,7 +680,7 @@ if there are still any actions you can take.

    -aliases = ['hold', 'wait']
    +aliases = ['wait', 'hold']
    @@ -706,7 +706,7 @@ if there are still any actions you can take.

    -search_index_entry = {'aliases': 'hold wait', 'category': 'combat', 'key': 'pass', 'no_prefix': ' hold wait', 'tags': '', 'text': '\n Passes on your turn.\n\n Usage:\n pass\n\n When in a fight, you can use this command to end your turn early, even\n if there are still any actions you can take.\n '}
    +search_index_entry = {'aliases': 'wait hold', 'category': 'combat', 'key': 'pass', 'no_prefix': ' wait hold', 'tags': '', 'text': '\n Passes on your turn.\n\n Usage:\n pass\n\n When in a fight, you can use this command to end your turn early, even\n if there are still any actions you can take.\n '}
    diff --git a/docs/2.x/api/evennia.contrib.game_systems.turnbattle.tb_equip.html b/docs/2.x/api/evennia.contrib.game_systems.turnbattle.tb_equip.html index 7ecb81b00c..8386735c09 100644 --- a/docs/2.x/api/evennia.contrib.game_systems.turnbattle.tb_equip.html +++ b/docs/2.x/api/evennia.contrib.game_systems.turnbattle.tb_equip.html @@ -575,7 +575,7 @@ if there are still any actions you can take.

    -aliases = ['hold', 'wait']
    +aliases = ['wait', 'hold']
    @@ -595,7 +595,7 @@ if there are still any actions you can take.

    -search_index_entry = {'aliases': 'hold wait', 'category': 'combat', 'key': 'pass', 'no_prefix': ' hold wait', 'tags': '', 'text': '\n Passes on your turn.\n\n Usage:\n pass\n\n When in a fight, you can use this command to end your turn early, even\n if there are still any actions you can take.\n '}
    +search_index_entry = {'aliases': 'wait hold', 'category': 'combat', 'key': 'pass', 'no_prefix': ' wait hold', 'tags': '', 'text': '\n Passes on your turn.\n\n Usage:\n pass\n\n When in a fight, you can use this command to end your turn early, even\n if there are still any actions you can take.\n '}
    diff --git a/docs/2.x/api/evennia.contrib.game_systems.turnbattle.tb_items.html b/docs/2.x/api/evennia.contrib.game_systems.turnbattle.tb_items.html index a9cb8ec2ad..5cdde30129 100644 --- a/docs/2.x/api/evennia.contrib.game_systems.turnbattle.tb_items.html +++ b/docs/2.x/api/evennia.contrib.game_systems.turnbattle.tb_items.html @@ -698,7 +698,7 @@ if there are still any actions you can take.

    -aliases = ['hold', 'wait']
    +aliases = ['wait', 'hold']
    @@ -718,7 +718,7 @@ if there are still any actions you can take.

    -search_index_entry = {'aliases': 'hold wait', 'category': 'combat', 'key': 'pass', 'no_prefix': ' hold wait', 'tags': '', 'text': '\n Passes on your turn.\n\n Usage:\n pass\n\n When in a fight, you can use this command to end your turn early, even\n if there are still any actions you can take.\n '}
    +search_index_entry = {'aliases': 'wait hold', 'category': 'combat', 'key': 'pass', 'no_prefix': ' wait hold', 'tags': '', 'text': '\n Passes on your turn.\n\n Usage:\n pass\n\n When in a fight, you can use this command to end your turn early, even\n if there are still any actions you can take.\n '}
    diff --git a/docs/2.x/api/evennia.contrib.game_systems.turnbattle.tb_magic.html b/docs/2.x/api/evennia.contrib.game_systems.turnbattle.tb_magic.html index 40f957d777..65ef8b98b2 100644 --- a/docs/2.x/api/evennia.contrib.game_systems.turnbattle.tb_magic.html +++ b/docs/2.x/api/evennia.contrib.game_systems.turnbattle.tb_magic.html @@ -477,7 +477,7 @@ if there are still any actions you can take.

    -aliases = ['hold', 'wait']
    +aliases = ['wait', 'hold']
    @@ -497,7 +497,7 @@ if there are still any actions you can take.

    -search_index_entry = {'aliases': 'hold wait', 'category': 'combat', 'key': 'pass', 'no_prefix': ' hold wait', 'tags': '', 'text': '\n Passes on your turn.\n\n Usage:\n pass\n\n When in a fight, you can use this command to end your turn early, even\n if there are still any actions you can take.\n '}
    +search_index_entry = {'aliases': 'wait hold', 'category': 'combat', 'key': 'pass', 'no_prefix': ' wait hold', 'tags': '', 'text': '\n Passes on your turn.\n\n Usage:\n pass\n\n When in a fight, you can use this command to end your turn early, even\n if there are still any actions you can take.\n '}
    diff --git a/docs/2.x/api/evennia.contrib.game_systems.turnbattle.tb_range.html b/docs/2.x/api/evennia.contrib.game_systems.turnbattle.tb_range.html index 3fb13400d7..464c87420b 100644 --- a/docs/2.x/api/evennia.contrib.game_systems.turnbattle.tb_range.html +++ b/docs/2.x/api/evennia.contrib.game_systems.turnbattle.tb_range.html @@ -937,7 +937,7 @@ if there are still any actions you can take.

    -aliases = ['hold', 'wait']
    +aliases = ['wait', 'hold']
    @@ -957,7 +957,7 @@ if there are still any actions you can take.

    -search_index_entry = {'aliases': 'hold wait', 'category': 'combat', 'key': 'pass', 'no_prefix': ' hold wait', 'tags': '', 'text': '\n Passes on your turn.\n\n Usage:\n pass\n\n When in a fight, you can use this command to end your turn early, even\n if there are still any actions you can take.\n '}
    +search_index_entry = {'aliases': 'wait hold', 'category': 'combat', 'key': 'pass', 'no_prefix': ' wait hold', 'tags': '', 'text': '\n Passes on your turn.\n\n Usage:\n pass\n\n When in a fight, you can use this command to end your turn early, even\n if there are still any actions you can take.\n '}
    diff --git a/docs/2.x/api/evennia.contrib.grid.extended_room.extended_room.html b/docs/2.x/api/evennia.contrib.grid.extended_room.extended_room.html index f161a9924f..44aed4cdec 100644 --- a/docs/2.x/api/evennia.contrib.grid.extended_room.extended_room.html +++ b/docs/2.x/api/evennia.contrib.grid.extended_room.extended_room.html @@ -651,7 +651,7 @@ look *<account&g
    -aliases = ['ls', 'l']
    +aliases = ['l', 'ls']
    @@ -671,7 +671,7 @@ look *<account&g
    -search_index_entry = {'aliases': 'ls l', 'category': 'general', 'key': 'look', 'no_prefix': ' ls l', 'tags': '', 'text': '\n look\n\n Usage:\n look\n look <obj>\n look <room detail>\n look *<account>\n\n Observes your location, details at your location or objects in your vicinity.\n '}
    +search_index_entry = {'aliases': 'l ls', 'category': 'general', 'key': 'look', 'no_prefix': ' l ls', 'tags': '', 'text': '\n look\n\n Usage:\n look\n look <obj>\n look <room detail>\n look *<account>\n\n Observes your location, details at your location or objects in your vicinity.\n '}
    diff --git a/docs/2.x/api/evennia.contrib.grid.xyzgrid.commands.html b/docs/2.x/api/evennia.contrib.grid.xyzgrid.commands.html index 652a2fef7e..f92fe04007 100644 --- a/docs/2.x/api/evennia.contrib.grid.xyzgrid.commands.html +++ b/docs/2.x/api/evennia.contrib.grid.xyzgrid.commands.html @@ -430,7 +430,7 @@ there is no room above/below you, your movement will fail.

    -aliases = ['fly', 'dive']
    +aliases = ['dive', 'fly']
    @@ -453,7 +453,7 @@ to all the variables defined therein.

    -search_index_entry = {'aliases': 'fly dive', 'category': 'general', 'key': 'fly or dive', 'no_prefix': ' fly dive', 'tags': '', 'text': '\n Fly or Dive up and down.\n\n Usage:\n fly\n dive\n\n Will fly up one room or dive down one room at your current position. If\n there is no room above/below you, your movement will fail.\n\n '}
    +search_index_entry = {'aliases': 'dive fly', 'category': 'general', 'key': 'fly or dive', 'no_prefix': ' dive fly', 'tags': '', 'text': '\n Fly or Dive up and down.\n\n Usage:\n fly\n dive\n\n Will fly up one room or dive down one room at your current position. If\n there is no room above/below you, your movement will fail.\n\n '}
    diff --git a/docs/2.x/api/evennia.contrib.rpg.dice.dice.html b/docs/2.x/api/evennia.contrib.rpg.dice.dice.html index f83eaba61b..5008628379 100644 --- a/docs/2.x/api/evennia.contrib.rpg.dice.dice.html +++ b/docs/2.x/api/evennia.contrib.rpg.dice.dice.html @@ -334,7 +334,7 @@ everyone but the person rolling.

    -aliases = ['@dice', 'roll']
    +aliases = ['roll', '@dice']
    @@ -360,7 +360,7 @@ everyone but the person rolling.

    -search_index_entry = {'aliases': '@dice roll', 'category': 'general', 'key': 'dice', 'no_prefix': ' dice roll', 'tags': '', 'text': "\n roll dice\n\n Usage:\n dice[/switch] <nr>d<sides> [modifier] [success condition]\n\n Switch:\n hidden - tell the room the roll is being done, but don't show the result\n secret - don't inform the room about neither roll nor result\n\n Examples:\n dice 3d6 + 4\n dice 1d100 - 2 < 50\n\n This will roll the given number of dice with given sides and modifiers.\n So e.g. 2d6 + 3 means to 'roll a 6-sided die 2 times and add the result,\n then add 3 to the total'.\n Accepted modifiers are +, -, * and /.\n A success condition is given as normal Python conditionals\n (<,>,<=,>=,==,!=). So e.g. 2d6 + 3 > 10 means that the roll will succeed\n only if the final result is above 8. If a success condition is given, the\n outcome (pass/fail) will be echoed along with how much it succeeded/failed\n with. The hidden/secret switches will hide all or parts of the roll from\n everyone but the person rolling.\n "}
    +search_index_entry = {'aliases': 'roll @dice', 'category': 'general', 'key': 'dice', 'no_prefix': ' roll dice', 'tags': '', 'text': "\n roll dice\n\n Usage:\n dice[/switch] <nr>d<sides> [modifier] [success condition]\n\n Switch:\n hidden - tell the room the roll is being done, but don't show the result\n secret - don't inform the room about neither roll nor result\n\n Examples:\n dice 3d6 + 4\n dice 1d100 - 2 < 50\n\n This will roll the given number of dice with given sides and modifiers.\n So e.g. 2d6 + 3 means to 'roll a 6-sided die 2 times and add the result,\n then add 3 to the total'.\n Accepted modifiers are +, -, * and /.\n A success condition is given as normal Python conditionals\n (<,>,<=,>=,==,!=). So e.g. 2d6 + 3 > 10 means that the roll will succeed\n only if the final result is above 8. If a success condition is given, the\n outcome (pass/fail) will be echoed along with how much it succeeded/failed\n with. The hidden/secret switches will hide all or parts of the roll from\n everyone but the person rolling.\n "}
    diff --git a/docs/2.x/api/evennia.contrib.rpg.llm.llm_client.html b/docs/2.x/api/evennia.contrib.rpg.llm.llm_client.html index 17de205ca0..08e4171f54 100644 --- a/docs/2.x/api/evennia.contrib.rpg.llm.llm_client.html +++ b/docs/2.x/api/evennia.contrib.rpg.llm.llm_client.html @@ -230,7 +230,9 @@ to this Protocol. The connection has been closed.

    Get a response from the LLM server for the given npc.

    Parameters
    -

    prompt (str) – The prompt to send to the LLM server.

    +

    prompt (str or list) – The prompt to send to the LLM server. If a list, +this is assumed to be the chat history so far, and will be added to the +prompt in a way suitable for the api.

    Returns

    str

    diff --git a/docs/2.x/api/evennia.contrib.rpg.llm.llm_npc.html b/docs/2.x/api/evennia.contrib.rpg.llm.llm_npc.html index 89295eaf00..168fa64449 100644 --- a/docs/2.x/api/evennia.contrib.rpg.llm.llm_npc.html +++ b/docs/2.x/api/evennia.contrib.rpg.llm.llm_npc.html @@ -122,6 +122,11 @@ echo a ‘thinking…’ message if the LLM server takes too long to respond.

    Bases: evennia.objects.objects.DefaultCharacter

    An NPC that uses the LLM server to generate its responses. If the server is slow, it will echo a thinking message to the character while it waits for a response.

    +
    +
    +prompt_prefix = None
    +
    +
    response_template = '$You() $conj(say) (to $You(character)): {response}'
    @@ -142,6 +147,13 @@ echo a thinking message to the character while it waits for a response.

    property llm_client
    +
    +
    +property llm_prompt_prefix
    +

    get prefix, first from Attribute, then from class variable, +then from settings, then from default

    +
    +
    at_talked_to(speech, character)[source]
    diff --git a/docs/2.x/api/evennia.contrib.rpg.rpsystem.rpsystem.html b/docs/2.x/api/evennia.contrib.rpg.rpsystem.rpsystem.html index c1c61a27f3..354dd6d3af 100644 --- a/docs/2.x/api/evennia.contrib.rpg.rpsystem.rpsystem.html +++ b/docs/2.x/api/evennia.contrib.rpg.rpsystem.rpsystem.html @@ -881,7 +881,7 @@ Using the command without arguments will list all current recogs.

    -aliases = ['recognize', 'forget']
    +aliases = ['forget', 'recognize']
    @@ -908,7 +908,7 @@ Using the command without arguments will list all current recogs.

    -search_index_entry = {'aliases': 'recognize forget', 'category': 'general', 'key': 'recog', 'no_prefix': ' recognize forget', 'tags': '', 'text': '\n Recognize another person in the same room.\n\n Usage:\n recog\n recog sdesc as alias\n forget alias\n\n Example:\n recog tall man as Griatch\n forget griatch\n\n This will assign a personal alias for a person, or forget said alias.\n Using the command without arguments will list all current recogs.\n\n '}
    +search_index_entry = {'aliases': 'forget recognize', 'category': 'general', 'key': 'recog', 'no_prefix': ' forget recognize', 'tags': '', 'text': '\n Recognize another person in the same room.\n\n Usage:\n recog\n recog sdesc as alias\n forget alias\n\n Example:\n recog tall man as Griatch\n forget griatch\n\n This will assign a personal alias for a person, or forget said alias.\n Using the command without arguments will list all current recogs.\n\n '}
    diff --git a/docs/2.x/api/evennia.contrib.tutorials.evadventure.combat_turnbased.html b/docs/2.x/api/evennia.contrib.tutorials.evadventure.combat_turnbased.html index 73fe4f65d0..5009392c4f 100644 --- a/docs/2.x/api/evennia.contrib.tutorials.evadventure.combat_turnbased.html +++ b/docs/2.x/api/evennia.contrib.tutorials.evadventure.combat_turnbased.html @@ -474,7 +474,7 @@ turn of combat, performing everyone’s actions in random order.

    -aliases = ['hit', 'turnbased combat']
    +aliases = ['turnbased combat', 'hit']
    @@ -520,7 +520,7 @@ set in self.parse())

    -search_index_entry = {'aliases': 'hit turnbased combat', 'category': 'general', 'key': 'attack', 'no_prefix': ' hit turnbased combat', 'tags': '', 'text': '\n Start or join combat.\n\n Usage:\n attack [<target>]\n\n '}
    +search_index_entry = {'aliases': 'turnbased combat hit', 'category': 'general', 'key': 'attack', 'no_prefix': ' turnbased combat hit', 'tags': '', 'text': '\n Start or join combat.\n\n Usage:\n attack [<target>]\n\n '}
    diff --git a/docs/2.x/api/evennia.contrib.tutorials.evadventure.combat_twitch.html b/docs/2.x/api/evennia.contrib.tutorials.evadventure.combat_twitch.html index 6775e22af1..c801039b1b 100644 --- a/docs/2.x/api/evennia.contrib.tutorials.evadventure.combat_twitch.html +++ b/docs/2.x/api/evennia.contrib.tutorials.evadventure.combat_twitch.html @@ -389,7 +389,7 @@ look *<account&g
    -aliases = ['ls', 'l']
    +aliases = ['l', 'ls']
    @@ -409,7 +409,7 @@ look *<account&g
    -search_index_entry = {'aliases': 'ls l', 'category': 'general', 'key': 'look', 'no_prefix': ' ls l', 'tags': '', 'text': '\n look at location or object\n\n Usage:\n look\n look <obj>\n look *<account>\n\n Observes your location or objects in your vicinity.\n '}
    +search_index_entry = {'aliases': 'l ls', 'category': 'general', 'key': 'look', 'no_prefix': ' l ls', 'tags': '', 'text': '\n look at location or object\n\n Usage:\n look\n look <obj>\n look *<account>\n\n Observes your location or objects in your vicinity.\n '}
    @@ -485,7 +485,7 @@ boost INT Wizard Goblin

    -aliases = ['foil', 'boost']
    +aliases = ['boost', 'foil']
    @@ -519,7 +519,7 @@ set in self.parse())

    -search_index_entry = {'aliases': 'foil boost', 'category': 'combat', 'key': 'stunt', 'no_prefix': ' foil boost', 'tags': '', 'text': '\n Perform a combat stunt, that boosts an ally against a target, or\n foils an enemy, giving them disadvantage against an ally.\n\n Usage:\n boost [ability] <recipient> <target>\n foil [ability] <recipient> <target>\n boost [ability] <target> (same as boost me <target>)\n foil [ability] <target> (same as foil <target> me)\n\n Example:\n boost STR me Goblin\n boost DEX Goblin\n foil STR Goblin me\n foil INT Goblin\n boost INT Wizard Goblin\n\n '}
    +search_index_entry = {'aliases': 'boost foil', 'category': 'combat', 'key': 'stunt', 'no_prefix': ' boost foil', 'tags': '', 'text': '\n Perform a combat stunt, that boosts an ally against a target, or\n foils an enemy, giving them disadvantage against an ally.\n\n Usage:\n boost [ability] <recipient> <target>\n foil [ability] <recipient> <target>\n boost [ability] <target> (same as boost me <target>)\n foil [ability] <target> (same as foil <target> me)\n\n Example:\n boost STR me Goblin\n boost DEX Goblin\n foil STR Goblin me\n foil INT Goblin\n boost INT Wizard Goblin\n\n '}
    diff --git a/docs/2.x/api/evennia.contrib.tutorials.evadventure.commands.html b/docs/2.x/api/evennia.contrib.tutorials.evadventure.commands.html index ed02b786fb..a8bfcc0523 100644 --- a/docs/2.x/api/evennia.contrib.tutorials.evadventure.commands.html +++ b/docs/2.x/api/evennia.contrib.tutorials.evadventure.commands.html @@ -200,7 +200,7 @@ self.args).

    -aliases = ['i', 'inv']
    +aliases = ['inv', 'i']
    @@ -224,7 +224,7 @@ set in self.parse())

    -search_index_entry = {'aliases': 'i inv', 'category': 'general', 'key': 'inventory', 'no_prefix': ' i inv', 'tags': '', 'text': '\n View your inventory\n\n Usage:\n inventory\n\n '}
    +search_index_entry = {'aliases': 'inv i', 'category': 'general', 'key': 'inventory', 'no_prefix': ' inv i', 'tags': '', 'text': '\n View your inventory\n\n Usage:\n inventory\n\n '}
    diff --git a/docs/2.x/api/evennia.contrib.tutorials.red_button.red_button.html b/docs/2.x/api/evennia.contrib.tutorials.red_button.red_button.html index afe395d18e..990e678c1c 100644 --- a/docs/2.x/api/evennia.contrib.tutorials.red_button.red_button.html +++ b/docs/2.x/api/evennia.contrib.tutorials.red_button.red_button.html @@ -514,7 +514,7 @@ be mutually exclusive.

    -aliases = ['feel', 'ex', 'l', 'listen', 'get', 'examine']
    +aliases = ['l', 'examine', 'ex', 'feel', 'get', 'listen']
    @@ -540,7 +540,7 @@ be mutually exclusive.

    -search_index_entry = {'aliases': 'feel ex l listen get examine', 'category': 'general', 'key': 'look', 'no_prefix': ' feel ex l listen get examine', 'tags': '', 'text': "\n Looking around in darkness\n\n Usage:\n look <obj>\n\n ... not that there's much to see in the dark.\n\n "}
    +search_index_entry = {'aliases': 'l examine ex feel get listen', 'category': 'general', 'key': 'look', 'no_prefix': ' l examine ex feel get listen', 'tags': '', 'text': "\n Looking around in darkness\n\n Usage:\n look <obj>\n\n ... not that there's much to see in the dark.\n\n "}
    diff --git a/docs/2.x/api/evennia.contrib.tutorials.tutorial_world.objects.html b/docs/2.x/api/evennia.contrib.tutorials.tutorial_world.objects.html index 181eb34331..9b91a798ac 100644 --- a/docs/2.x/api/evennia.contrib.tutorials.tutorial_world.objects.html +++ b/docs/2.x/api/evennia.contrib.tutorials.tutorial_world.objects.html @@ -564,7 +564,7 @@ shift green root up/down

    -aliases = ['move', 'shiftroot', 'pull', 'push']
    +aliases = ['shiftroot', 'move', 'pull', 'push']
    @@ -600,7 +600,7 @@ yellow/green - horizontal roots

    -search_index_entry = {'aliases': 'move shiftroot pull push', 'category': 'tutorialworld', 'key': 'shift', 'no_prefix': ' move shiftroot pull push', 'tags': '', 'text': '\n Shifts roots around.\n\n Usage:\n shift blue root left/right\n shift red root left/right\n shift yellow root up/down\n shift green root up/down\n\n '}
    +search_index_entry = {'aliases': 'shiftroot move pull push', 'category': 'tutorialworld', 'key': 'shift', 'no_prefix': ' shiftroot move pull push', 'tags': '', 'text': '\n Shifts roots around.\n\n Usage:\n shift blue root left/right\n shift red root left/right\n shift yellow root up/down\n shift green root up/down\n\n '}
    @@ -617,7 +617,7 @@ yellow/green - horizontal roots

    -aliases = ['button', 'press button', 'push button']
    +aliases = ['push button', 'button', 'press button']
    @@ -643,7 +643,7 @@ yellow/green - horizontal roots

    -search_index_entry = {'aliases': 'button press button push button', 'category': 'tutorialworld', 'key': 'press', 'no_prefix': ' button press button push button', 'tags': '', 'text': '\n Presses a button.\n '}
    +search_index_entry = {'aliases': 'push button button press button', 'category': 'tutorialworld', 'key': 'press', 'no_prefix': ' push button button press button', 'tags': '', 'text': '\n Presses a button.\n '}
    @@ -787,7 +787,7 @@ parry - forgoes your attack but will make you harder to hit on next

    -aliases = ['fight', 'hit', 'parry', 'bash', 'stab', 'chop', 'kill', 'slash', 'pierce', 'defend', 'thrust']
    +aliases = ['fight', 'chop', 'defend', 'pierce', 'thrust', 'kill', 'bash', 'slash', 'parry', 'hit', 'stab']
    @@ -813,7 +813,7 @@ parry - forgoes your attack but will make you harder to hit on next

    -search_index_entry = {'aliases': 'fight hit parry bash stab chop kill slash pierce defend thrust', 'category': 'tutorialworld', 'key': 'attack', 'no_prefix': ' fight hit parry bash stab chop kill slash pierce defend thrust', 'tags': '', 'text': '\n Attack the enemy. Commands:\n\n stab <enemy>\n slash <enemy>\n parry\n\n stab - (thrust) makes a lot of damage but is harder to hit with.\n slash - is easier to land, but does not make as much damage.\n parry - forgoes your attack but will make you harder to hit on next\n enemy attack.\n\n '}
    +search_index_entry = {'aliases': 'fight chop defend pierce thrust kill bash slash parry hit stab', 'category': 'tutorialworld', 'key': 'attack', 'no_prefix': ' fight chop defend pierce thrust kill bash slash parry hit stab', 'tags': '', 'text': '\n Attack the enemy. Commands:\n\n stab <enemy>\n slash <enemy>\n parry\n\n stab - (thrust) makes a lot of damage but is harder to hit with.\n slash - is easier to land, but does not make as much damage.\n parry - forgoes your attack but will make you harder to hit on next\n enemy attack.\n\n '}
    diff --git a/docs/2.x/api/evennia.contrib.tutorials.tutorial_world.rooms.html b/docs/2.x/api/evennia.contrib.tutorials.tutorial_world.rooms.html index 07eac7e15c..03e0b5a0b3 100644 --- a/docs/2.x/api/evennia.contrib.tutorials.tutorial_world.rooms.html +++ b/docs/2.x/api/evennia.contrib.tutorials.tutorial_world.rooms.html @@ -256,7 +256,7 @@ code except for adding in the details.

    -aliases = ['ls', 'l']
    +aliases = ['l', 'ls']
    @@ -271,7 +271,7 @@ code except for adding in the details.

    -search_index_entry = {'aliases': 'ls l', 'category': 'tutorialworld', 'key': 'look', 'no_prefix': ' ls l', 'tags': '', 'text': '\n looks at the room and on details\n\n Usage:\n look <obj>\n look <room detail>\n look *<account>\n\n Observes your location, details at your location or objects\n in your vicinity.\n\n Tutorial: This is a child of the default Look command, that also\n allows us to look at "details" in the room. These details are\n things to examine and offers some extra description without\n actually having to be actual database objects. It uses the\n return_detail() hook on TutorialRooms for this.\n '}
    +search_index_entry = {'aliases': 'l ls', 'category': 'tutorialworld', 'key': 'look', 'no_prefix': ' l ls', 'tags': '', 'text': '\n looks at the room and on details\n\n Usage:\n look <obj>\n look <room detail>\n look *<account>\n\n Observes your location, details at your location or objects\n in your vicinity.\n\n Tutorial: This is a child of the default Look command, that also\n allows us to look at "details" in the room. These details are\n things to examine and offers some extra description without\n actually having to be actual database objects. It uses the\n return_detail() hook on TutorialRooms for this.\n '}
    @@ -824,7 +824,7 @@ if they fall off the bridge.

    -aliases = ['?', 'h']
    +aliases = ['h', '?']
    @@ -850,7 +850,7 @@ if they fall off the bridge.

    -search_index_entry = {'aliases': '? h', 'category': 'tutorial world', 'key': 'help', 'no_prefix': ' ? h', 'tags': '', 'text': '\n Overwritten help command while on the bridge.\n '}
    +search_index_entry = {'aliases': 'h ?', 'category': 'tutorial world', 'key': 'help', 'no_prefix': ' h ?', 'tags': '', 'text': '\n Overwritten help command while on the bridge.\n '}
    @@ -976,7 +976,7 @@ to find something.

    -aliases = ['feel', 'fiddle', 'l', 'search', 'feel around']
    +aliases = ['l', 'search', 'fiddle', 'feel', 'feel around']
    @@ -1004,7 +1004,7 @@ random chance of eventually finding a light source.

    -search_index_entry = {'aliases': 'feel fiddle l search feel around', 'category': 'tutorialworld', 'key': 'look', 'no_prefix': ' feel fiddle l search feel around', 'tags': '', 'text': '\n Look around in darkness\n\n Usage:\n look\n\n Look around in the darkness, trying\n to find something.\n '}
    +search_index_entry = {'aliases': 'l search fiddle feel feel around', 'category': 'tutorialworld', 'key': 'look', 'no_prefix': ' l search fiddle feel feel around', 'tags': '', 'text': '\n Look around in darkness\n\n Usage:\n look\n\n Look around in the darkness, trying\n to find something.\n '}
    diff --git a/docs/2.x/api/evennia.contrib.utils.git_integration.git_integration.html b/docs/2.x/api/evennia.contrib.utils.git_integration.git_integration.html index 74bd994db0..9a0e89d289 100644 --- a/docs/2.x/api/evennia.contrib.utils.git_integration.git_integration.html +++ b/docs/2.x/api/evennia.contrib.utils.git_integration.git_integration.html @@ -216,7 +216,7 @@ git evennia pull - Pull the latest evennia code.

    -directory = '/tmp/tmpry4ablff/812642bbfdc6881c208c56ca311807c32b7bba5e/evennia'
    +directory = '/tmp/tmpulxo9thq/06fdeabc34bf2e297fef06ae18077fb34993b062/evennia'
    @@ -277,7 +277,7 @@ git pull - Pull the latest code from your current branch.

    -directory = '/tmp/tmpry4ablff/812642bbfdc6881c208c56ca311807c32b7bba5e/evennia/game_template'
    +directory = '/tmp/tmpulxo9thq/06fdeabc34bf2e297fef06ae18077fb34993b062/evennia/game_template'
    diff --git a/docs/2.x/api/evennia.utils.eveditor.html b/docs/2.x/api/evennia.utils.eveditor.html index 7619788af6..f7623593eb 100644 --- a/docs/2.x/api/evennia.utils.eveditor.html +++ b/docs/2.x/api/evennia.utils.eveditor.html @@ -344,7 +344,7 @@ indentation.

    -aliases = [':q!', ':I', ':echo', ':h', ':wq', ':i', ':::', ':=', ':fi', ':!', ':<', ':DD', ':dd', ':p', ':q', ':>', ':s', '::', ':A', ':u', ':y', ':j', ':dw', ':f', ':r', ':', ':UU', ':x', ':S', ':fd', ':w', ':uu']
    +aliases = [':w', ':r', ':dd', ':uu', ':fi', ':<', ':j', '::', ':x', ':I', ':u', ':A', ':!', ':dw', ':y', ':=', ':S', ':s', ':wq', ':fd', ':i', ':h', ':UU', ':DD', ':p', ':q!', ':f', ':echo', ':::', ':', ':>', ':q']
    @@ -372,7 +372,7 @@ efficient presentation.

    -search_index_entry = {'aliases': ':q! :I :echo :h :wq :i ::: := :fi :! :< :DD :dd :p :q :> :s :: :A :u :y :j :dw :f :r : :UU :x :S :fd :w :uu', 'category': 'general', 'key': ':editor_command_group', 'no_prefix': ' :q! :I :echo :h :wq :i ::: := :fi :! :< :DD :dd :p :q :> :s :: :A :u :y :j :dw :f :r : :UU :x :S :fd :w :uu', 'tags': '', 'text': '\n Commands for the editor\n '}
    +search_index_entry = {'aliases': ':w :r :dd :uu :fi :< :j :: :x :I :u :A :! :dw :y := :S :s :wq :fd :i :h :UU :DD :p :q! :f :echo ::: : :> :q', 'category': 'general', 'key': ':editor_command_group', 'no_prefix': ' :w :r :dd :uu :fi :< :j :: :x :I :u :A :! :dw :y := :S :s :wq :fd :i :h :UU :DD :p :q! :f :echo ::: : :> :q', 'tags': '', 'text': '\n Commands for the editor\n '}
    diff --git a/docs/2.x/api/evennia.utils.evmenu.html b/docs/2.x/api/evennia.utils.evmenu.html index 6a85715136..4c555197f7 100644 --- a/docs/2.x/api/evennia.utils.evmenu.html +++ b/docs/2.x/api/evennia.utils.evmenu.html @@ -939,7 +939,7 @@ single question.

    -aliases = ['yes', 'a', '__nomatch_command', 'abort', 'n', 'y', 'no']
    +aliases = ['no', 'y', 'abort', '__nomatch_command', 'n', 'yes', 'a']
    @@ -965,7 +965,7 @@ single question.

    -search_index_entry = {'aliases': 'yes a __nomatch_command abort n y no', 'category': 'general', 'key': '__noinput_command', 'no_prefix': ' yes a __nomatch_command abort n y no', 'tags': '', 'text': '\n Handle a prompt for yes or no. Press [return] for the default choice.\n\n '}
    +search_index_entry = {'aliases': 'no y abort __nomatch_command n yes a', 'category': 'general', 'key': '__noinput_command', 'no_prefix': ' no y abort __nomatch_command n yes a', 'tags': '', 'text': '\n Handle a prompt for yes or no. Press [return] for the default choice.\n\n '}
    diff --git a/docs/2.x/api/evennia.utils.evmore.html b/docs/2.x/api/evennia.utils.evmore.html index c7e9c5e1a8..ec44771ee0 100644 --- a/docs/2.x/api/evennia.utils.evmore.html +++ b/docs/2.x/api/evennia.utils.evmore.html @@ -145,7 +145,7 @@ the caller.msg() construct every time the page is updated.

    -aliases = ['a', 't', 'abort', 'end', 'previous', 'q', 'n', 'quit', 'next', 'p', 'top', 'e']
    +aliases = ['e', 't', 'next', 'end', 'abort', 'p', 'quit', 'n', 'previous', 'top', 'a', 'q']
    @@ -171,7 +171,7 @@ the caller.msg() construct every time the page is updated.

    -search_index_entry = {'aliases': 'a t abort end previous q n quit next p top e', 'category': 'general', 'key': '__noinput_command', 'no_prefix': ' a t abort end previous q n quit next p top e', 'tags': '', 'text': '\n Manipulate the text paging. Catch no-input with aliases.\n '}
    +search_index_entry = {'aliases': 'e t next end abort p quit n previous top a q', 'category': 'general', 'key': '__noinput_command', 'no_prefix': ' e t next end abort p quit n previous top a q', 'tags': '', 'text': '\n Manipulate the text paging. Catch no-input with aliases.\n '}
    diff --git a/docs/2.x/genindex.html b/docs/2.x/genindex.html index 7bc14f2d48..c588024d4b 100644 --- a/docs/2.x/genindex.html +++ b/docs/2.x/genindex.html @@ -13184,6 +13184,8 @@
  • ljust() (evennia.utils.ansi.ANSIString method)
  • llm_client() (evennia.contrib.rpg.llm.llm_npc.LLMNPC property) +
  • +
  • llm_prompt_prefix() (evennia.contrib.rpg.llm.llm_npc.LLMNPC property)
  • LLMClient (class in evennia.contrib.rpg.llm.llm_client)
  • @@ -17440,6 +17442,8 @@
  • (evennia.contrib.tutorials.evadventure.quests.EvAdventureQuestHandler method)
  • +
  • prompt_prefix (evennia.contrib.rpg.llm.llm_npc.LLMNPC attribute) +
  • pronoun_to_viewpoints() (in module evennia.utils.verb_conjugation.pronouns)
  • protfunc_callable_protkey() (in module evennia.prototypes.protfuncs) diff --git a/docs/2.x/objects.inv b/docs/2.x/objects.inv index e98be2f586a2c721b52cb19ff1cd7c7365a19276..b2d032b882bba2874d78202a57783e9c857326e2 100644 GIT binary patch delta 132784 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