mirror of
https://github.com/evennia/evennia.git
synced 2026-04-02 05:57:16 +02:00
Merge branch 'evennia:main' into hex_colors
This commit is contained in:
commit
aa9ed83a26
9 changed files with 55 additions and 31 deletions
|
|
@ -5,8 +5,14 @@
|
|||
- [Feature][pull3470]: New `exit_order` kwarg to
|
||||
`DefaultObject.get_display_exits` to easier customize the order in which
|
||||
standard exits are displayed in a room (chiizujin)
|
||||
- [Fix][pull3495]: Fix rate in Trait contribs not updating after reload (jaborsh)
|
||||
- [Fix][pull3491]: Fix traceback in EvEditor when searching with malformed regex (chiizujin)
|
||||
- [Docs]: Doc fixes (Griatch, chiizujin)
|
||||
|
||||
[pull3470]: https://github.com/evennia/evennia/pull/3470
|
||||
[pull3495]: https://github.com/evennia/evennia/pull/3495
|
||||
[pull3491]: https://github.com/evennia/evennia/pull/3491
|
||||
|
||||
|
||||
## Evennia 4.1.1
|
||||
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ ABILITY_REVERSE_MAP = {
|
|||
|
||||
Above, the `Ability` class holds some basic properties of a character sheet.
|
||||
|
||||
The `ABILITY_REVERSE_MAP` is a convenient map to go the other way &mdas; if in some command we were to enter the string 'cha', we could use this mapping to directly convert your input to the correct `Ability`. For example:
|
||||
The `ABILITY_REVERSE_MAP` is a convenient map to go the other way — if in some command we were to enter the string 'cha', we could use this mapping to directly convert your input to the correct `Ability`. For example:
|
||||
|
||||
ability = ABILITY_REVERSE_MAP.get(your_input)
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,7 @@ This file contains the Descriptors used to set Fields in Components
|
|||
|
||||
import typing
|
||||
|
||||
from evennia.typeclasses.attributes import (AttributeProperty,
|
||||
NAttributeProperty)
|
||||
from evennia.typeclasses.attributes import AttributeProperty, NAttributeProperty
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
from .components import Component
|
||||
|
|
|
|||
|
|
@ -268,7 +268,7 @@ class TestComponents(EvenniaTest):
|
|||
|
||||
def test_mutables_are_not_shared_when_autocreate(self):
|
||||
self.char1.test_a.my_list.append(1)
|
||||
self.assertNotEqual(id(self.char1.test_a.my_list), id(self.char2.test_a.my_list))
|
||||
self.assertIsNot(self.char1.test_a.my_list, self.char2.test_a.my_list)
|
||||
|
||||
def test_replacing_class_component_slot_with_runtime_component(self):
|
||||
self.char1.components.add_default("replacement_inherited_test_a")
|
||||
|
|
|
|||
|
|
@ -661,7 +661,12 @@ class TraitHandler:
|
|||
return trait
|
||||
|
||||
def add(
|
||||
self, trait_key, name=None, trait_type=DEFAULT_TRAIT_TYPE, force=True, **trait_properties
|
||||
self,
|
||||
trait_key,
|
||||
name=None,
|
||||
trait_type=DEFAULT_TRAIT_TYPE,
|
||||
force=True,
|
||||
**trait_properties,
|
||||
):
|
||||
"""
|
||||
Create a new Trait and add it to the handler.
|
||||
|
|
@ -945,7 +950,12 @@ class Trait:
|
|||
|
||||
def __getattr__(self, key):
|
||||
"""Access extra parameters as attributes."""
|
||||
if key in ("default_keys", "data_default", "trait_type", "allow_extra_properties"):
|
||||
if key in (
|
||||
"default_keys",
|
||||
"data_default",
|
||||
"trait_type",
|
||||
"allow_extra_properties",
|
||||
):
|
||||
return _GA(self, key)
|
||||
try:
|
||||
return self._data[key]
|
||||
|
|
@ -1276,7 +1286,7 @@ class CounterTrait(Trait):
|
|||
)
|
||||
# set up rate
|
||||
if trait_data["rate"] != 0:
|
||||
trait_data["last_update"] = time()
|
||||
trait_data["last_update"] = trait_data.get("last_update", time())
|
||||
else:
|
||||
trait_data["last_update"] = None
|
||||
return trait_data
|
||||
|
|
@ -1552,6 +1562,7 @@ class GaugeTrait(CounterTrait):
|
|||
rate = self.rate
|
||||
if rate != 0 and self._data["last_update"] is not None:
|
||||
now = time()
|
||||
|
||||
tdiff = now - self._data["last_update"]
|
||||
current += rate * tdiff
|
||||
value = current
|
||||
|
|
|
|||
|
|
@ -1588,6 +1588,7 @@ class DefaultObject(ObjectDB, metaclass=TypeclassBase):
|
|||
obj.get_display_name(looker, exit_order=('north', 'south'))
|
||||
-> "Exits: north, south, out, and portal." (markup not shown here)
|
||||
"""
|
||||
|
||||
def _sort_exit_names(names):
|
||||
exit_order = kwargs.get("exit_order")
|
||||
if not exit_order:
|
||||
|
|
@ -1595,7 +1596,7 @@ class DefaultObject(ObjectDB, metaclass=TypeclassBase):
|
|||
sort_index = {name: key for key, name in enumerate(exit_order)}
|
||||
names = sorted(names)
|
||||
end_pos = len(names) + 1
|
||||
names.sort(key=lambda name:sort_index.get(name, end_pos))
|
||||
names.sort(key=lambda name: sort_index.get(name, end_pos))
|
||||
return names
|
||||
|
||||
exits = self.filter_visible(self.contents_get(content_type="exit"), looker, **kwargs)
|
||||
|
|
|
|||
|
|
@ -3,8 +3,12 @@ from unittest import skip
|
|||
from evennia import DefaultCharacter, DefaultExit, DefaultObject, DefaultRoom
|
||||
from evennia.objects.models import ObjectDB
|
||||
from evennia.typeclasses.attributes import AttributeProperty
|
||||
from evennia.typeclasses.tags import (AliasProperty, PermissionProperty,
|
||||
TagCategoryProperty, TagProperty)
|
||||
from evennia.typeclasses.tags import (
|
||||
AliasProperty,
|
||||
PermissionProperty,
|
||||
TagCategoryProperty,
|
||||
TagProperty,
|
||||
)
|
||||
from evennia.utils import create, search
|
||||
from evennia.utils.ansi import strip_ansi
|
||||
from evennia.utils.test_resources import BaseEvenniaTest, EvenniaTestCase
|
||||
|
|
@ -102,7 +106,7 @@ class DefaultObjectTest(BaseEvenniaTest):
|
|||
self.assertEqual(exits, "Exits: out, south, portal, north, and aperture")
|
||||
|
||||
# in specified order with unspecified exits alpbabetically on the end
|
||||
exit_order = ('north', 'south', 'out')
|
||||
exit_order = ("north", "south", "out")
|
||||
exits = strip_ansi(self.room1.get_display_exits(self.char1, exit_order=exit_order))
|
||||
self.assertEqual(exits, "Exits: north, south, out, aperture, and portal")
|
||||
|
||||
|
|
@ -589,7 +593,6 @@ class TestProperties(EvenniaTestCase):
|
|||
# check cross-instance sharing
|
||||
self.assertEqual(obj2.attr5, [], "cross-instance sharing detected")
|
||||
|
||||
|
||||
def test_mutable_defaults__autocreate_false(self):
|
||||
"""
|
||||
Test https://github.com/evennia/evennia/issues/3488, where a mutable default value (like a
|
||||
|
|
@ -631,7 +634,6 @@ class TestProperties(EvenniaTestCase):
|
|||
# check cross-instance sharing
|
||||
self.assertEqual(obj2.attr7, [])
|
||||
|
||||
|
||||
def test_mutable_defaults__autocreate_true(self):
|
||||
"""
|
||||
Test mutable defaults with autocreate=True.
|
||||
|
|
@ -652,4 +654,3 @@ class TestProperties(EvenniaTestCase):
|
|||
|
||||
obj1.delete()
|
||||
obj2.delete()
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ from copy import copy
|
|||
from django.conf import settings
|
||||
from django.db import models
|
||||
from django.utils.encoding import smart_str
|
||||
|
||||
from evennia.locks.lockhandler import LockHandler
|
||||
from evennia.utils.dbserialize import from_pickle, to_pickle
|
||||
from evennia.utils.idmapper.models import SharedMemoryModel
|
||||
|
|
|
|||
|
|
@ -654,29 +654,34 @@ class CmdEditorGroup(CmdEditorBase):
|
|||
if not self.linerange:
|
||||
lstart = 0
|
||||
lend = self.cline + 1
|
||||
caller.msg(
|
||||
_("Search-replaced {arg1} -> {arg2} for lines {l1}-{l2}.").format(
|
||||
arg1=self.arg1, arg2=self.arg2, l1=lstart + 1, l2=lend
|
||||
)
|
||||
)
|
||||
else:
|
||||
caller.msg(
|
||||
_("Search-replaced {arg1} -> {arg2} for {line}.").format(
|
||||
arg1=self.arg1, arg2=self.arg2, line=self.lstr
|
||||
)
|
||||
)
|
||||
sarea = "\n".join(linebuffer[lstart:lend])
|
||||
|
||||
regex = r"%s|^%s(?=\s)|(?<=\s)%s(?=\s)|^%s$|(?<=\s)%s$"
|
||||
regarg = self.arg1.strip("'").strip('"')
|
||||
if " " in regarg:
|
||||
regarg = regarg.replace(" ", " +")
|
||||
sarea = re.sub(
|
||||
regex % (regarg, regarg, regarg, regarg, regarg),
|
||||
self.arg2.strip("'").strip('"'),
|
||||
sarea,
|
||||
re.MULTILINE,
|
||||
)
|
||||
try:
|
||||
sarea = re.sub(
|
||||
regex % (regarg, regarg, regarg, regarg, regarg),
|
||||
self.arg2.strip("'").strip('"'),
|
||||
sarea,
|
||||
re.MULTILINE,
|
||||
)
|
||||
except re.error as e:
|
||||
caller.msg(_("Invalid regular expression."))
|
||||
else:
|
||||
if not self.linerange:
|
||||
caller.msg(
|
||||
_("Search-replaced {arg1} -> {arg2} for lines {l1}-{l2}.").format(
|
||||
arg1=self.arg1, arg2=self.arg2, l1=lstart + 1, l2=lend
|
||||
)
|
||||
)
|
||||
else:
|
||||
caller.msg(
|
||||
_("Search-replaced {arg1} -> {arg2} for {line}.").format(
|
||||
arg1=self.arg1, arg2=self.arg2, line=self.lstr
|
||||
)
|
||||
)
|
||||
buf = linebuffer[:lstart] + sarea.split("\n") + linebuffer[lend:]
|
||||
editor.update_buffer(buf)
|
||||
elif cmd == ":f":
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue