From 0fb67ccad931b721372c4c53f620173e0224b114 Mon Sep 17 00:00:00 2001 From: Tonalmictli Date: Sun, 9 Apr 2023 23:38:08 -0700 Subject: [PATCH 01/18] Update Beginner-Tutorial-Rules.md --- .../Howtos/Beginner-Tutorial/Part3/Beginner-Tutorial-Rules.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/Howtos/Beginner-Tutorial/Part3/Beginner-Tutorial-Rules.md b/docs/source/Howtos/Beginner-Tutorial/Part3/Beginner-Tutorial-Rules.md index 20e5ca4b0d..1456dc23f5 100644 --- a/docs/source/Howtos/Beginner-Tutorial/Part3/Beginner-Tutorial-Rules.md +++ b/docs/source/Howtos/Beginner-Tutorial/Part3/Beginner-Tutorial-Rules.md @@ -320,7 +320,7 @@ class EvAdventureRollEngine: defender_defense = getattr(defender, defense_type.value, 1) + 10 result, quality = self.saving_throw(attacker, bonus_type=attack_type, target=defender_defense, - advantage=advantave, disadvantage=disadvantage) + advantage=advantage, disadvantage=disadvantage) return result, quality ``` From 2776294e2aaf123c35eddcbf552d9fb717ebe358 Mon Sep 17 00:00:00 2001 From: Tonalmictli Date: Mon, 10 Apr 2023 00:30:26 -0700 Subject: [PATCH 02/18] Update Beginner-Tutorial-Rules.md Added missing parenthesis. --- .../Howtos/Beginner-Tutorial/Part3/Beginner-Tutorial-Rules.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/Howtos/Beginner-Tutorial/Part3/Beginner-Tutorial-Rules.md b/docs/source/Howtos/Beginner-Tutorial/Part3/Beginner-Tutorial-Rules.md index 1456dc23f5..4b585259f8 100644 --- a/docs/source/Howtos/Beginner-Tutorial/Part3/Beginner-Tutorial-Rules.md +++ b/docs/source/Howtos/Beginner-Tutorial/Part3/Beginner-Tutorial-Rules.md @@ -584,7 +584,7 @@ class TestEvAdventureRuleEngine(BaseEvenniaTest): @patch("evadventure.rules.randint") def test_roll(self, mock_randint): mock_randint.return_value = 4 - self.assertEqual(self.roll_engine.roll("1d6", 4) + self.assertEqual(self.roll_engine.roll("1d6", 4)) self.assertEqual(self.roll_engine.roll("2d6", 2 * 4) # test of the other rule methods below ... From d522e75b6857a774f009545b5b3d1ad3379d758a Mon Sep 17 00:00:00 2001 From: Tonalmictli Date: Mon, 10 Apr 2023 00:52:07 -0700 Subject: [PATCH 03/18] Update Beginner-Tutorial-Rules.md Closing another parenthesis --- .../Howtos/Beginner-Tutorial/Part3/Beginner-Tutorial-Rules.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/Howtos/Beginner-Tutorial/Part3/Beginner-Tutorial-Rules.md b/docs/source/Howtos/Beginner-Tutorial/Part3/Beginner-Tutorial-Rules.md index 4b585259f8..bcf3311b4f 100644 --- a/docs/source/Howtos/Beginner-Tutorial/Part3/Beginner-Tutorial-Rules.md +++ b/docs/source/Howtos/Beginner-Tutorial/Part3/Beginner-Tutorial-Rules.md @@ -585,7 +585,7 @@ class TestEvAdventureRuleEngine(BaseEvenniaTest): def test_roll(self, mock_randint): mock_randint.return_value = 4 self.assertEqual(self.roll_engine.roll("1d6", 4)) - self.assertEqual(self.roll_engine.roll("2d6", 2 * 4) + self.assertEqual(self.roll_engine.roll("2d6"), 2 * 4) # test of the other rule methods below ... ``` From 3d214609fc7acde19da4c73f62971b2f8bf51efa Mon Sep 17 00:00:00 2001 From: Bradley Marques Date: Mon, 10 Apr 2023 12:14:39 +0200 Subject: [PATCH 04/18] Adds some notes and a cross-reference in Rooms documentaion. --- docs/source/Components/Exits.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/docs/source/Components/Exits.md b/docs/source/Components/Exits.md index 17770a2b76..91964dfab6 100644 --- a/docs/source/Components/Exits.md +++ b/docs/source/Components/Exits.md @@ -19,6 +19,8 @@ *Exits* are in-game [Objects](./Objects.md) connecting other objects (usually [Rooms](./Rooms.md)) together. +> Note that Exits are one-way objects, so in order for two rooms to be linked bi-directionally, there will need to be two exits. + An object named `north` or `in` might be exits, as well as `door`, `portal` or `jump out the window`. An exit has two things that separate them from other objects. @@ -29,7 +31,7 @@ The default exit functionality is all defined on the [DefaultExit](DefaultExit) Exits are [locked](./Locks.md) using an `access_type` called *traverse* and also make use of a few hook methods for giving feedback if the traversal fails. See `evennia.DefaultExit` for more info. -Exits are normally overridden on a case-by-case basis, but if you want to change the default exit createad by rooms like `dig` , `tunnel` or `open` you can change it in settings: +Exits are normally overridden on a case-by-case basis, but if you want to change the default exit created by rooms like `dig` , `tunnel` or `open` you can change it in settings: BASE_EXIT_TYPECLASS = "typeclasses.exits.Exit" @@ -52,4 +54,8 @@ The process of traversing an exit is as follows: 1. `obj.at_post_move(source)` 1. On the Exit object, `at_post_traverse(obj, source)` is triggered. -If the move fails for whatever reason, the Exit will look for an Attribute `err_traverse` on itself and display this as an error message. If this is not found, the Exit will instead call `at_failed_traverse(obj)` on itself. \ No newline at end of file +If the move fails for whatever reason, the Exit will look for an Attribute `err_traverse` on itself and display this as an error message. If this is not found, the Exit will instead call `at_failed_traverse(obj)` on itself. + +### Creating Exits in code + +For an example of how to create Exits programatically please see [this guide](../Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Creating-Things.md#linking-exits-and-rooms-in-code). From 112880a1c177dae9d2daf30cb4335018fdbe24ef Mon Sep 17 00:00:00 2001 From: Bradley Marques Date: Mon, 10 Apr 2023 12:18:01 +0200 Subject: [PATCH 05/18] Capitalizes 'Room' --- docs/source/Components/Exits.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/Components/Exits.md b/docs/source/Components/Exits.md index 91964dfab6..e3cf5de630 100644 --- a/docs/source/Components/Exits.md +++ b/docs/source/Components/Exits.md @@ -19,7 +19,7 @@ *Exits* are in-game [Objects](./Objects.md) connecting other objects (usually [Rooms](./Rooms.md)) together. -> Note that Exits are one-way objects, so in order for two rooms to be linked bi-directionally, there will need to be two exits. +> Note that Exits are one-way objects, so in order for two Rooms to be linked bi-directionally, there will need to be two exits. An object named `north` or `in` might be exits, as well as `door`, `portal` or `jump out the window`. From d47e0e057d2e81ffc5285a69965a72e0d57aec15 Mon Sep 17 00:00:00 2001 From: Bradley Marques Date: Mon, 10 Apr 2023 12:18:30 +0200 Subject: [PATCH 06/18] Removes extra whitespace --- docs/source/Components/Exits.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/Components/Exits.md b/docs/source/Components/Exits.md index e3cf5de630..02a6f73a2a 100644 --- a/docs/source/Components/Exits.md +++ b/docs/source/Components/Exits.md @@ -31,7 +31,7 @@ The default exit functionality is all defined on the [DefaultExit](DefaultExit) Exits are [locked](./Locks.md) using an `access_type` called *traverse* and also make use of a few hook methods for giving feedback if the traversal fails. See `evennia.DefaultExit` for more info. -Exits are normally overridden on a case-by-case basis, but if you want to change the default exit created by rooms like `dig` , `tunnel` or `open` you can change it in settings: +Exits are normally overridden on a case-by-case basis, but if you want to change the default exit created by rooms like `dig`, `tunnel` or `open` you can change it in settings: BASE_EXIT_TYPECLASS = "typeclasses.exits.Exit" From b65827c82720b47eb851964ccc6f317a7eccccf6 Mon Sep 17 00:00:00 2001 From: Dpeta <69427753+Dpeta@users.noreply.github.com> Date: Sun, 16 Apr 2023 22:46:48 +0200 Subject: [PATCH 07/18] Fix a few docs typos. --- docs/source/Components/Channels.md | 12 ++++++------ docs/source/Components/Locks.md | 4 ++-- docs/source/Concepts/Internationalization.md | 4 ++-- .../Part1/Beginner-Tutorial-Building-Quickstart.md | 8 ++++---- .../source/Howtos/Implementing-a-game-rule-system.md | 4 ++-- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/docs/source/Components/Channels.md b/docs/source/Components/Channels.md index 4f2527e40d..b125373c34 100644 --- a/docs/source/Components/Channels.md +++ b/docs/source/Components/Channels.md @@ -17,8 +17,8 @@ Channels can be used both for chats between [Accounts](./Accounts.md) and betwee - Private guild channels for planning and organization (IC/OOC depending on game) - Cyberpunk-style retro chat rooms (IC) - In-game radio channels (IC) -- Group telephathy (IC) -- Walkie talkies (IC) +- Group telepathy (IC) +- Walkie-talkies (IC) ```{versionchanged} 1.0 @@ -150,7 +150,7 @@ To create/destroy a new channel on the fly you can do Aliases are optional but can be good for obvious shortcuts everyone may want to use. The description is used in channel-listings. You will automatically join a channel you created and will be controlling it. You can also use `channel/desc` to -change the description on a channel you wnn later. +change the description on a channel you own later. If you control a channel you can also kick people off it: @@ -223,7 +223,7 @@ channels you could override the `help` command and change the lockstring to: ``` -Add this custom command to your default cmdset and regular users wil now get an +Add this custom command to your default cmdset and regular users will now get an access-denied error when trying to use use these switches. ## Using channels in code @@ -263,7 +263,7 @@ below: 3. `channel.at_post_channel_msg(message, **kwargs)` Note that `Accounts` and `Objects` both have their have separate sets of hooks. -So make sure you modify the set actually used by your subcribers (or both). +So make sure you modify the set actually used by your subscribers (or both). Default channels all use `Account` subscribers. ### Channel class @@ -379,7 +379,7 @@ Notable `Channel` hooks: a class-method that will happily remove found channel-aliases from the user linked to _any_ channel, not only from the channel the method is called on. - `pre_join_channel(subscriber)` - if this returns `False`, connection will be refused. -- `post_join_channel(subscriber)` - by default this sets up a users's channel-nicks/aliases. +- `post_join_channel(subscriber)` - by default this sets up a users' channel-nicks/aliases. - `pre_leave_channel(subscriber)` - if this returns `False`, the user is not allowed to leave. - `post_leave_channel(subscriber)` - this will clean up any channel aliases/nicks of the user. - `delete` the standard typeclass-delete mechanism will also automatically un-subscribe all diff --git a/docs/source/Components/Locks.md b/docs/source/Components/Locks.md index 486a918d3e..f306b9505c 100644 --- a/docs/source/Components/Locks.md +++ b/docs/source/Components/Locks.md @@ -104,7 +104,7 @@ Below are the access_types checked by the default commandset. - `search` - this controls if the object can be found with the `DefaultObject.search` method (usually referred to with `caller.search` in Commands). This is how to create entirely 'undetectable' in-game objects. - If not setting this lock excplicitly, all objects are assumed searchable. + If not setting this lock explicitly, all objects are assumed searchable. Note that if you are aiming to make some _permanently invisible game system, using a [Script](./Scripts.md) is a better bet. - `get`- who may pick up the object and carry it around. @@ -330,7 +330,7 @@ error message. Sounds good! Let's start by setting that on the box: Next we need to craft a Lock of type *get* on our box. We want it to only be passed if the accessing object has the attribute *strength* of the right value. For this we would need to create a lock function that checks if attributes have a value greater than a given value. Luckily there is already -such a one included in evennia (see `evennia/locks/lockfuncs.py`), called `attr_gt`. +such a one included in Evennia (see `evennia/locks/lockfuncs.py`), called `attr_gt`. So the lock string will look like this: `get:attr_gt(strength, 50)`. We put this on the box now: diff --git a/docs/source/Concepts/Internationalization.md b/docs/source/Concepts/Internationalization.md index fcf6733615..fc9b53deb5 100644 --- a/docs/source/Concepts/Internationalization.md +++ b/docs/source/Concepts/Internationalization.md @@ -84,11 +84,11 @@ Translations are found in the core `evennia/` library, under `evennia/evennia/locale/`. You must make sure to have cloned this repository from [Evennia's github](github:evennia) before you can proceed. -If you cannot find your language in `evennia/evennia/locale/` it's because noone +If you cannot find your language in `evennia/evennia/locale/` it's because no one has translated it yet. Alternatively you might have the language but find the translation bad ... You are welcome to help improve the situation! -To start a new translation you need to first have cloned the Evennia repositry +To start a new translation you need to first have cloned the Evennia repository with GIT and activated a python virtualenv as described on the [Setup Quickstart](../Setup/Installation.md) page. diff --git a/docs/source/Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Building-Quickstart.md b/docs/source/Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Building-Quickstart.md index 78863d6412..c35ecf1713 100644 --- a/docs/source/Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Building-Quickstart.md +++ b/docs/source/Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Building-Quickstart.md @@ -100,7 +100,7 @@ If you try the `get` command, we will pick up the box. So far so good, but if we lock box = get:false() -Locks represent a rather [big topic](../../../Components/Locks.md), but for now that will do what we want. This will lock the box so noone can lift it. The exception is superusers, they override all locks and will pick it +Locks represent a rather [big topic](../../../Components/Locks.md), but for now that will do what we want. This will lock the box so no one can lift it. The exception is superusers, they override all locks and will pick it up anyway. Make sure you are quelling your superuser powers and try to get the box now: > get box @@ -142,7 +142,7 @@ You create your own scripts in Python, outside the game; the path you give to `s ## Pushing Your Buttons -If we get back to the box we made, there is only so much fun you can have with it at this point. It's just a dumb generic object. If you renamed it to `stone` and changed its description, noone would be the wiser. However, with the combined use of custom [Typeclasses](../../../Components/Typeclasses.md), [Scripts](../../../Components/Scripts.md) +If we get back to the box we made, there is only so much fun you can have with it at this point. It's just a dumb generic object. If you renamed it to `stone` and changed its description, no one would be the wiser. However, with the combined use of custom [Typeclasses](../../../Components/Typeclasses.md), [Scripts](../../../Components/Scripts.md) and object-based [Commands](../../../Components/Commands.md), you could expand it and other items to be as unique, complex and interactive as you want. @@ -153,7 +153,7 @@ Let's make us one of _those_! create/drop button:tutorials.red_button.RedButton -The same way we did with the Script Earler, we specify a "Python-path" to the Python code we want Evennia to use for creating the object. There you go - one red button. +The same way we did with the Script earlier, we specify a "Python-path" to the Python code we want Evennia to use for creating the object. There you go - one red button. The RedButton is an example object intended to show off a few of Evennia's features. You will find that the [Typeclass](../../../Components/Typeclasses.md) and [Commands](../../../Components/Commands.md) controlling it are inside [evennia/contrib/tutorials/red_button](../../../api/evennia.contrib.tutorials.red_button.md) @@ -240,4 +240,4 @@ You will now find your new `History` entry in the `help` list and read your help ## Adding a World -After this brief introduction to building and using in-game commands you may be ready to see a more fleshed-out example. Evennia comes with a tutorial world for you to explore. We will try that out in the next lesson. \ No newline at end of file +After this brief introduction to building and using in-game commands you may be ready to see a more fleshed-out example. Evennia comes with a tutorial world for you to explore. We will try that out in the next lesson. diff --git a/docs/source/Howtos/Implementing-a-game-rule-system.md b/docs/source/Howtos/Implementing-a-game-rule-system.md index 10b23cd70e..d3419cd5aa 100644 --- a/docs/source/Howtos/Implementing-a-game-rule-system.md +++ b/docs/source/Howtos/Implementing-a-game-rule-system.md @@ -11,7 +11,7 @@ are very dedicated. Many games, even the most roleplay-dedicated, thus tend to allow for players to mediate themselves to some extent. A common way to do this is to introduce *coded systems* - that is, to let the computer do some of the heavy lifting. A basic thing is to add an online dice-roller so everyone can -make rolls and make sure noone is cheating. Somewhere at this level you find the most bare-bones +make rolls and make sure no one is cheating. Somewhere at this level you find the most bare-bones roleplaying MUSHes. The advantage of a coded system is that as long as the rules are fair the computer is too - it makes @@ -236,4 +236,4 @@ Note how simple the command becomes and how generic you can make it. It becomes number of Combat commands by just extending this functionality - you can easily roll challenges and pick different skills to check. And if you ever decided to, say, change how to determine hit chance, you don't have to change every command, but need only change the single `roll_hit` function inside -your `rules` module. \ No newline at end of file +your `rules` module. From 616daf723a9bb912313cf2f7d6f2c802cd81f236 Mon Sep 17 00:00:00 2001 From: Griatch Date: Fri, 21 Apr 2023 00:25:57 +0200 Subject: [PATCH 08/18] Fix username-validator errors not showing in web registration form --- CHANGELOG.md | 4 +++- evennia/accounts/accounts.py | 10 +--------- evennia/server/validators.py | 5 +---- evennia/web/website/views/accounts.py | 25 +++++++++---------------- 4 files changed, 14 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e75fcdd06..f1a047ae00 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,9 @@ ## Main branch -- Feature: Better ANSI color fallbacks (InspectorCaracal) +- Fix: The username validator did not display errors correctly in web + registration form. +- Feature: Better ANSI color fallbacks (InspectorCaracal). - Feature: Add support for saving `deque` with `maxlen` to Attributes (before `maxlen` was ignored). - Tools: More unit tests for scripts (Storsorken) diff --git a/evennia/accounts/accounts.py b/evennia/accounts/accounts.py index 1a46cdbc19..3c1708c72d 100644 --- a/evennia/accounts/accounts.py +++ b/evennia/accounts/accounts.py @@ -20,7 +20,6 @@ from django.core.exceptions import ImproperlyConfigured, ValidationError from django.utils import timezone from django.utils.module_loading import import_string from django.utils.translation import gettext as _ - from evennia.accounts.manager import AccountManager from evennia.accounts.models import AccountDB from evennia.commands.cmdsethandler import CmdSetHandler @@ -38,13 +37,7 @@ from evennia.typeclasses.attributes import ModelAttributeBackend, NickHandler from evennia.typeclasses.models import TypeclassBase from evennia.utils import class_from_module, create, logger from evennia.utils.optionhandler import OptionHandler -from evennia.utils.utils import ( - is_iter, - lazy_property, - make_iter, - to_str, - variable_from_module, -) +from evennia.utils.utils import is_iter, lazy_property, make_iter, to_str, variable_from_module __all__ = ("DefaultAccount", "DefaultGuest") @@ -509,7 +502,6 @@ class DefaultAccount(AccountDB, metaclass=TypeclassBase): Returns: validators (list): List of instantiated Validator objects. """ - objs = [] for validator in validator_config: try: diff --git a/evennia/server/validators.py b/evennia/server/validators.py index f03ce0b161..234a52fbef 100644 --- a/evennia/server/validators.py +++ b/evennia/server/validators.py @@ -3,7 +3,6 @@ import re from django.conf import settings from django.core.exceptions import ValidationError from django.utils.translation import gettext as _ - from evennia.accounts.models import AccountDB @@ -24,7 +23,6 @@ class EvenniaUsernameAvailabilityValidator: raises ValidationError otherwise. """ - # Check guest list if settings.GUEST_LIST and username.lower() in ( guest.lower() for guest in settings.GUEST_LIST @@ -45,8 +43,7 @@ class EvenniaPasswordValidator: def __init__( self, regex=r"^[\w. @+\-',]+$", - policy="Password should contain a mix of letters, " - "spaces, digits and @/./+/-/_/'/, only.", + policy="Password should contain a mix of letters, spaces, digits and @/./+/-/_/'/, only.", ): """ Constructs a standard Django password validator. diff --git a/evennia/web/website/views/accounts.py b/evennia/web/website/views/accounts.py index 4964d3d567..70a811dee7 100644 --- a/evennia/web/website/views/accounts.py +++ b/evennia/web/website/views/accounts.py @@ -8,7 +8,6 @@ from django.conf import settings from django.contrib import messages from django.http import HttpResponseRedirect from django.urls import reverse_lazy - from evennia.utils import class_from_module from evennia.web.website import forms @@ -56,22 +55,16 @@ class AccountCreateView(AccountMixin, EvenniaCreateView): password = form.cleaned_data["password1"] email = form.cleaned_data.get("email", "") - # Create account + # Create account. This also runs all validations on the username/password. account, errs = self.typeclass.create(username=username, password=password, email=email) - # If unsuccessful, display error messages to user if not account: - [messages.error(self.request, err) for err in errs] - - # Call the Django "form failure" hook + # password validation happens earlier, only username checks appear here. + form.add_error("username", ", ".join(errs)) return self.form_invalid(form) - - # Inform user of success - messages.success( - self.request, - "Your account '%s' was successfully created! " - "You may log in using it now." % account.name, - ) - - # Redirect the user to the login page - return HttpResponseRedirect(self.success_url) + else: + # Inform user of success + messages.success( + self.request, f"Your account '{account.name}' was successfully created!" + ) + return HttpResponseRedirect(self.success_url) From aeaeada75ee6ae770fa8cdd90965c6c5469a2b0b Mon Sep 17 00:00:00 2001 From: Bradley Marques Date: Fri, 21 Apr 2023 21:44:49 +0200 Subject: [PATCH 09/18] Empty commit to rerun CI From 33da3d803182c2aa89e98ac41a5cc5275b7a5264 Mon Sep 17 00:00:00 2001 From: Bradley Marques Date: Fri, 21 Apr 2023 22:00:42 +0200 Subject: [PATCH 10/18] Adds tearDown() to flush id cache --- evennia/utils/test_resources.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/evennia/utils/test_resources.py b/evennia/utils/test_resources.py index 158a940ee3..4e05499eeb 100644 --- a/evennia/utils/test_resources.py +++ b/evennia/utils/test_resources.py @@ -558,9 +558,19 @@ class EvenniaTestCase(TestCase): """ For use with gamedir settings; Just like the normal test case, only for naming consistency. + Notes: + + - Inheriting from this class will bypass EvenniaTestMixin, and therefore + not setup some default objects. This can result in faster tests. + + - If you do inherit from this class for your unit tests, and have + overridden the tearDown() method, please also call flush_cache(). Not + doing so will result in flakey and order-dependent tests due to the + Django ID cache not being flushed. """ - pass + def tearDown(self) -> None: + flush_cache() @override_settings(**DEFAULT_SETTINGS) From 36bdfad772d9ce16031bcdd2d4f085e28de1cfd4 Mon Sep 17 00:00:00 2001 From: Bradley Marques Date: Fri, 21 Apr 2023 22:01:42 +0200 Subject: [PATCH 11/18] Fixes typo --- docs/source/Coding/Unit-Testing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/Coding/Unit-Testing.md b/docs/source/Coding/Unit-Testing.md index ce47c2452a..b4825a3c44 100644 --- a/docs/source/Coding/Unit-Testing.md +++ b/docs/source/Coding/Unit-Testing.md @@ -106,7 +106,7 @@ To test this, run to run the entire test module - evennia test --settings setings.py world.tests + evennia test --settings settings.py world.tests or a specific class: From b13e4499cacf0f79309848a6f7772e9f8aa1424d Mon Sep 17 00:00:00 2001 From: homeofpoe Date: Mon, 24 Apr 2023 14:46:31 -0700 Subject: [PATCH 12/18] Update README.md Fix header levels --- evennia/contrib/base_systems/components/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/evennia/contrib/base_systems/components/README.md b/evennia/contrib/base_systems/components/README.md index 7446419617..7e430c19c5 100644 --- a/evennia/contrib/base_systems/components/README.md +++ b/evennia/contrib/base_systems/components/README.md @@ -2,23 +2,23 @@ _Contrib by ChrisLR 2021_ -# The Components Contrib +## The Components Contrib This contrib introduces Components and Composition to Evennia. Each 'Component' class represents a feature that will be 'enabled' on a typeclass instance. You can register these components on an entire typeclass or a single object at runtime. It supports both persisted attributes and in-memory attributes by using Evennia's AttributeHandler. -# Pros +## Pros - You can reuse a feature across multiple typeclasses without inheritance - You can cleanly organize each feature into a self-contained class. - You can check if your object supports a feature without checking its instance. -# Cons +## Cons - It introduces additional complexity. - A host typeclass instance is required. -# How to install +## How to install To enable component support for a typeclass, import and inherit the ComponentHolderMixin, similar to this @@ -126,7 +126,7 @@ from typeclasses.components import health ``` Both of the above examples will work. -# Full Example +## Full Example ```python from evennia.contrib.base_systems import components From 720b843d61c4a101564bdf783ea3bb213140b3a4 Mon Sep 17 00:00:00 2001 From: Wendy Wang Date: Tue, 25 Apr 2023 13:03:20 +0200 Subject: [PATCH 13/18] Typo fix for doc issue #3172 https://github.com/evennia/evennia/issues/3172 --- docs/source/Howtos/Tutorial-NPC-Merchants.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/Howtos/Tutorial-NPC-Merchants.md b/docs/source/Howtos/Tutorial-NPC-Merchants.md index 89b8d033cf..3c27841a75 100644 --- a/docs/source/Howtos/Tutorial-NPC-Merchants.md +++ b/docs/source/Howtos/Tutorial-NPC-Merchants.md @@ -54,7 +54,7 @@ class NPCMerchant(Object): def open_shop(self, shopper): menunodes = {} # TODO! shopname = self.db.shopname or "The shop" - EvMenu(shopper, menunodes, startnode="shop_start", + EvMenu(shopper, menunodes, startnode="shopfront", shopname=shopname, shopkeeper=self, wares=self.contents) ``` @@ -215,7 +215,7 @@ class NPCMerchant(Object): "inspect_and_buy": node_inspect_and_buy } shopname = self.db.shopname or "The shop" - EvMenu(shopper, menunodes, startnode="shop_start", + EvMenu(shopper, menunodes, startnode="shopfront", shopname=shopname, shopkeeper=self, wares=self.contents) ``` From bc92bad15a18c8f2a83dc029085569b715e69159 Mon Sep 17 00:00:00 2001 From: Griatch Date: Sat, 29 Apr 2023 08:00:32 +0200 Subject: [PATCH 14/18] Add proper header to components contrib --- evennia/contrib/base_systems/components/README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/evennia/contrib/base_systems/components/README.md b/evennia/contrib/base_systems/components/README.md index 7e430c19c5..0a7d0d01e5 100644 --- a/evennia/contrib/base_systems/components/README.md +++ b/evennia/contrib/base_systems/components/README.md @@ -1,6 +1,8 @@ # Components -_Contrib by ChrisLR 2021_ +Contrib by ChrisLR, 2021 + +Expand typeclasses using a components/composition approach. ## The Components Contrib @@ -134,7 +136,7 @@ from evennia.contrib.base_systems import components # This is the Component class class Health(components.Component): name = "health" - + # Stores the current and max values as Attributes on the host, defaulting to 100 current = components.DBField(default=100) max = components.DBField(default=100) @@ -185,7 +187,7 @@ class Attack(Command): # Attempt to retrieve the component, None is obtained if it does not exist. if target.components.health: valid_target = target - + if not valid_target: caller.msg("You can't attack that!") return True From 879d1d3f79d81b032ba3c2f7090d1ac6da7bee3c Mon Sep 17 00:00:00 2001 From: Griatch Date: Sat, 29 Apr 2023 08:02:00 +0200 Subject: [PATCH 15/18] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f1a047ae00..c3ff4ad6e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - Tools: More unit tests for scripts (Storsorken) - Fix: Components contrib had issues with inherited typeclasses (ChrisLR) - Fix: f-string fix in clothing contrib (aMiss-aWry) +- Fix: Have `EvenniaTestCase` properly flush idmapper cache (bradleymarques) - Docs: Made separate doc pages for Exits, Characters and Rooms. Expanded on how to change the description of an in-game object with templating. - Docs: A multitude of doc issues and typos fixed. From 3e6e074bd3da351475f1a981c28003646e128173 Mon Sep 17 00:00:00 2001 From: Griatch Date: Sat, 29 Apr 2023 08:13:49 +0200 Subject: [PATCH 16/18] Fix bug in CmdPage. Resolve #3166 --- evennia/commands/default/comms.py | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/evennia/commands/default/comms.py b/evennia/commands/default/comms.py index 679e6416ed..8a1762d784 100644 --- a/evennia/commands/default/comms.py +++ b/evennia/commands/default/comms.py @@ -8,7 +8,6 @@ Communication commands: """ from django.conf import settings - from evennia.accounts import bots from evennia.accounts.models import AccountDB from evennia.comms.comms import DefaultChannel @@ -777,7 +776,6 @@ class CmdChannel(COMMAND_DEFAULT_CLASS): maxwidth=_DEFAULT_WIDTH, ) for chan in subscribed: - locks = "-" chanid = "-" if chan.access(self.caller, "control"): @@ -1158,7 +1156,6 @@ class CmdChannel(COMMAND_DEFAULT_CLASS): reason = reason[0].strip() if reason else "" for chan in channels: - if not chan.access(caller, "control"): self.msg(f"You need 'control'-access to boot a user from {chan.key}.") return @@ -1245,9 +1242,11 @@ class CmdChannel(COMMAND_DEFAULT_CLASS): ) ask_yes_no( caller, - f"Are you sure you want to ban user {target.key} from " - f"channel(s) {channames} (make sure name/channels are correct{reasonwarn}) " - "{options}?", + ( + f"Are you sure you want to ban user {target.key} from " + f"channel(s) {channames} (make sure name/channels are correct{reasonwarn}) " + "{options}?" + ), _ban_user, "Aborted.", ) @@ -1360,7 +1359,7 @@ class CmdPage(COMMAND_DEFAULT_CLASS): targets.append(target_obj) message = self.rhs.strip() else: - target, *message = self.args.split(" ", 4) + target, *message = self.args.split(" ", 1) if target and target.isnumeric(): # a number to specify a historic page number = int(target) @@ -1970,7 +1969,8 @@ class CmdDiscord2Chan(COMMAND_DEFAULT_CLASS): if not discord_bot.is_typeclass(settings.DISCORD_BOT_CLASS, exact=True): self.msg( - f"WARNING: The Discord bot's typeclass is '{discord_bot.typeclass_path}'. This does not match {settings.DISCORD_BOT_CLASS} in settings!" + f"WARNING: The Discord bot's typeclass is '{discord_bot.typeclass_path}'. This does" + f" not match {settings.DISCORD_BOT_CLASS} in settings!" ) if "start" in self.switches: @@ -1984,13 +1984,15 @@ class CmdDiscord2Chan(COMMAND_DEFAULT_CLASS): if "guild" in self.switches: discord_bot.db.tag_guild = not discord_bot.db.tag_guild self.msg( - f"Messages to Evennia |wwill {'' if discord_bot.db.tag_guild else 'not '}|ninclude the Discord server." + f"Messages to Evennia |wwill {'' if discord_bot.db.tag_guild else 'not '}|ninclude" + " the Discord server." ) return if "channel" in self.switches: discord_bot.db.tag_channel = not discord_bot.db.tag_channel self.msg( - f"Relayed messages |wwill {'' if discord_bot.db.tag_channel else 'not '}|ninclude the originating channel." + f"Relayed messages |wwill {'' if discord_bot.db.tag_channel else 'not '}|ninclude" + " the originating channel." ) return @@ -2029,7 +2031,8 @@ class CmdDiscord2Chan(COMMAND_DEFAULT_CLASS): dc_chan_names = discord_bot.attributes.get("discord_channels", {}) dc_info = dc_chan_names.get(dc_chan, {"name": "unknown", "guild": "unknown"}) self.msg( - f"Removed link between {ev_chan} and #{dc_info.get('name','?')}@{dc_info.get('guild','?')}" + f"Removed link between {ev_chan} and" + f" #{dc_info.get('name','?')}@{dc_info.get('guild','?')}" ) return else: From bc0023072d2f51a8d06a2a22f608fea0d0234e28 Mon Sep 17 00:00:00 2001 From: Griatch Date: Sat, 29 Apr 2023 08:28:30 +0200 Subject: [PATCH 17/18] Expand sqlite issue to Mac troubleshooting doc. Resolve #3143 --- docs/source/Setup/Installation-Troubleshooting.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/Setup/Installation-Troubleshooting.md b/docs/source/Setup/Installation-Troubleshooting.md index cebfe986bb..9d8164896b 100644 --- a/docs/source/Setup/Installation-Troubleshooting.md +++ b/docs/source/Setup/Installation-Troubleshooting.md @@ -78,6 +78,7 @@ If `localhost` doesn't work when trying to connect to your local game, try `127. ## Mac Troubleshooting - Some Mac users have reported not being able to connect to `localhost` (i.e. your own computer). If so, try to connect to `127.0.0.1` instead, which is the same thing. Use port 4000 from mud clients and port 4001 from the web browser as usual. +- If you get a `MemoryError` when starting Evennia, or when looking at the log, this may be due to an sqlite versioning issue. [A user in our forums](https://github.com/evennia/evennia/discussions/2638#discussioncomment-3630761) found a working solution for this. [Here](https://github.com/evennia/evennia/issues/3120#issuecomment-1442540538) is another variation to solve it. ## Windows Troubleshooting From d6b5425a9e6846cde8d8564f5c268582861fbf8b Mon Sep 17 00:00:00 2001 From: Griatch Date: Sat, 29 Apr 2023 08:52:29 +0200 Subject: [PATCH 18/18] Evennia 1.3.0 minor release --- CHANGELOG.md | 10 ++++++---- docs/Makefile | 4 ++-- docs/source/Coding/Changelog.md | 14 +++++++++++--- docs/source/Contribs/Contrib-Components.md | 18 ++++++++++-------- docs/source/Contribs/Contribs-Overview.md | 4 ++-- evennia/VERSION.txt | 2 +- pyproject.toml | 2 +- 7 files changed, 33 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c3ff4ad6e5..8bf926bd25 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,16 +1,18 @@ # Changelog -## Main branch +## Evennia 1.3.0 + +Apr 29, 2023 -- Fix: The username validator did not display errors correctly in web - registration form. - Feature: Better ANSI color fallbacks (InspectorCaracal). - Feature: Add support for saving `deque` with `maxlen` to Attributes (before `maxlen` was ignored). -- Tools: More unit tests for scripts (Storsorken) +- Fix: The username validator did not display errors correctly in web + registration form. - Fix: Components contrib had issues with inherited typeclasses (ChrisLR) - Fix: f-string fix in clothing contrib (aMiss-aWry) - Fix: Have `EvenniaTestCase` properly flush idmapper cache (bradleymarques) +- Tools: More unit tests for scripts (Storsorken) - Docs: Made separate doc pages for Exits, Characters and Rooms. Expanded on how to change the description of an in-game object with templating. - Docs: A multitude of doc issues and typos fixed. diff --git a/docs/Makefile b/docs/Makefile index 6ecb864bc5..9d6484977c 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -58,10 +58,10 @@ _multiversion-check-env: @EVDIR=$(EVDIR) EVGAMEDIR=$(EVGAMEDIR) bash -e checkenv.sh multiversion _clean_api_index: - rm source/api/* + rm -f source/api/* _clean_api_rsts: - rm source/api/*.rst + rm -f source/api/*.rst # remove superfluos 'module' and 'package' text from api headers _reformat_apidoc_headers: diff --git a/docs/source/Coding/Changelog.md b/docs/source/Coding/Changelog.md index 3e475f97ca..8bf926bd25 100644 --- a/docs/source/Coding/Changelog.md +++ b/docs/source/Coding/Changelog.md @@ -1,13 +1,21 @@ # Changelog -## Main branch +## Evennia 1.3.0 +Apr 29, 2023 + +- Feature: Better ANSI color fallbacks (InspectorCaracal). - Feature: Add support for saving `deque` with `maxlen` to Attributes (before `maxlen` was ignored). -- Fix: More unit tests for scripts (Storsorken) +- Fix: The username validator did not display errors correctly in web + registration form. +- Fix: Components contrib had issues with inherited typeclasses (ChrisLR) +- Fix: f-string fix in clothing contrib (aMiss-aWry) +- Fix: Have `EvenniaTestCase` properly flush idmapper cache (bradleymarques) +- Tools: More unit tests for scripts (Storsorken) - Docs: Made separate doc pages for Exits, Characters and Rooms. Expanded on how to change the description of an in-game object with templating. -- Docs: Fixed a multitude of doc issues. +- Docs: A multitude of doc issues and typos fixed. ## Evennia 1.2.1 diff --git a/docs/source/Contribs/Contrib-Components.md b/docs/source/Contribs/Contrib-Components.md index aa221f860e..2e12a11cef 100644 --- a/docs/source/Contribs/Contrib-Components.md +++ b/docs/source/Contribs/Contrib-Components.md @@ -1,24 +1,26 @@ # Components -_Contrib by ChrisLR 2021_ +Contrib by ChrisLR, 2021 -# The Components Contrib +Expand typeclasses using a components/composition approach. + +## The Components Contrib This contrib introduces Components and Composition to Evennia. Each 'Component' class represents a feature that will be 'enabled' on a typeclass instance. You can register these components on an entire typeclass or a single object at runtime. It supports both persisted attributes and in-memory attributes by using Evennia's AttributeHandler. -# Pros +## Pros - You can reuse a feature across multiple typeclasses without inheritance - You can cleanly organize each feature into a self-contained class. - You can check if your object supports a feature without checking its instance. -# Cons +## Cons - It introduces additional complexity. - A host typeclass instance is required. -# How to install +## How to install To enable component support for a typeclass, import and inherit the ComponentHolderMixin, similar to this @@ -126,7 +128,7 @@ from typeclasses.components import health ``` Both of the above examples will work. -# Full Example +## Full Example ```python from evennia.contrib.base_systems import components @@ -134,7 +136,7 @@ from evennia.contrib.base_systems import components # This is the Component class class Health(components.Component): name = "health" - + # Stores the current and max values as Attributes on the host, defaulting to 100 current = components.DBField(default=100) max = components.DBField(default=100) @@ -185,7 +187,7 @@ class Attack(Command): # Attempt to retrieve the component, None is obtained if it does not exist. if target.components.health: valid_target = target - + if not valid_target: caller.msg("You can't attack that!") return True diff --git a/docs/source/Contribs/Contribs-Overview.md b/docs/source/Contribs/Contribs-Overview.md index 3a5d025929..684dffa859 100644 --- a/docs/source/Contribs/Contribs-Overview.md +++ b/docs/source/Contribs/Contribs-Overview.md @@ -111,9 +111,9 @@ Additional color markup styles for Evennia (extending or replacing the default ### `components` -__Contrib by ChrisLR 2021__ +_Contrib by ChrisLR, 2021_ -# The Components Contrib +Expand typeclasses using a components/composition approach. [Read the documentation](./Contrib-Components.md) - [Browse the Code](evennia.contrib.base_systems.components) diff --git a/evennia/VERSION.txt b/evennia/VERSION.txt index 6085e94650..f0bb29e763 100644 --- a/evennia/VERSION.txt +++ b/evennia/VERSION.txt @@ -1 +1 @@ -1.2.1 +1.3.0 diff --git a/pyproject.toml b/pyproject.toml index 2534c1b68f..78832c8620 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "evennia" -version = "1.2.1" +version = "1.3.0" maintainers = [{ name = "Griatch", email = "griatch@gmail.com" }] description = "A full-featured toolkit and server for text-based multiplayer games (MUDs, MU*, etc)." requires-python = ">=3.10"