Add Account.uses_screenreader. Added evadventure mini-map

This commit is contained in:
Griatch 2022-07-24 23:09:53 +02:00
parent 306d6b44aa
commit c95c8213a0
5 changed files with 69 additions and 32 deletions

View file

@ -178,6 +178,8 @@ Up requirements to Django 4.0+, Twisted 22+, Python 3.9 or 3.10
move being done ('teleport', 'disembark', 'give' etc). (volund) move being done ('teleport', 'disembark', 'give' etc). (volund)
- Made RPSystem contrib msg calls pass `pose` or `say` as msg-`type` for use in - Made RPSystem contrib msg calls pass `pose` or `say` as msg-`type` for use in
e.g. webclient pane filtering where desired. (volund) e.g. webclient pane filtering where desired. (volund)
- Added `Account.uses_screenreader(session=None)` as a quick shortcut for
finding if a user uses a screenreader (and adjust display accordingly).
## Evennia 0.9.5 ## Evennia 0.9.5

View file

@ -12,32 +12,32 @@ instead for most things).
""" """
import re import re
import time import time
from random import getrandbits
from django.conf import settings from django.conf import settings
from django.contrib.auth import authenticate, password_validation from django.contrib.auth import authenticate, password_validation
from django.core.exceptions import ImproperlyConfigured, ValidationError from django.core.exceptions import ImproperlyConfigured, ValidationError
from django.utils import timezone from django.utils import timezone
from django.utils.module_loading import import_string from django.utils.module_loading import import_string
from evennia.typeclasses.models import TypeclassBase from django.utils.translation import gettext as _
from evennia.accounts.manager import AccountManager from evennia.accounts.manager import AccountManager
from evennia.accounts.models import AccountDB from evennia.accounts.models import AccountDB
from evennia.objects.models import ObjectDB from evennia.commands.cmdsethandler import CmdSetHandler
from evennia.comms.models import ChannelDB from evennia.comms.models import ChannelDB
from evennia.objects.models import ObjectDB
from evennia.scripts.scripthandler import ScriptHandler
from evennia.server.models import ServerConfig from evennia.server.models import ServerConfig
from evennia.server.throttle import Throttle
from evennia.utils import class_from_module, create, logger
from evennia.utils.utils import lazy_property, to_str, make_iter, is_iter, variable_from_module
from evennia.server.signals import ( from evennia.server.signals import (
SIGNAL_ACCOUNT_POST_CREATE, SIGNAL_ACCOUNT_POST_CREATE,
SIGNAL_OBJECT_POST_PUPPET, SIGNAL_OBJECT_POST_PUPPET,
SIGNAL_OBJECT_POST_UNPUPPET, SIGNAL_OBJECT_POST_UNPUPPET,
) )
from evennia.typeclasses.attributes import NickHandler, ModelAttributeBackend from evennia.server.throttle import Throttle
from evennia.scripts.scripthandler import ScriptHandler from evennia.typeclasses.attributes import ModelAttributeBackend, NickHandler
from evennia.commands.cmdsethandler import CmdSetHandler from evennia.typeclasses.models import TypeclassBase
from evennia.utils import class_from_module, create, logger
from evennia.utils.optionhandler import OptionHandler from evennia.utils.optionhandler import OptionHandler
from evennia.utils.utils import is_iter, lazy_property, make_iter, to_str, variable_from_module
from django.utils.translation import gettext as _
from random import getrandbits
__all__ = ("DefaultAccount", "DefaultGuest") __all__ = ("DefaultAccount", "DefaultGuest")
@ -237,6 +237,22 @@ class DefaultAccount(AccountDB, metaclass=TypeclassBase):
return objs return objs
def uses_screenreader(self, session=None):
"""
Shortcut to determine if a session uses a screenreader. If no session given,
will return true if any of the sessions use a screenreader.
Args:
session (Session, optional): The session to check for screen reader.
"""
if session:
return bool(session.protocol_flags.get("SCREENREADER", False))
else:
return any(
session.protocol_flags.get("SCREENREADER") for session in self.sessions.all()
)
def get_display_name(self, looker, **kwargs): def get_display_name(self, looker, **kwargs):
""" """
This is used by channels and other OOC communications methods to give a This is used by channels and other OOC communications methods to give a

View file

@ -1,15 +1,24 @@
""" """
EvAdventure rooms. EvAdventure rooms.
The base EvAdventure room has a modified display header that shows a little mini-map.
All EvAdventure rooms inherit from this room, and it is integral to combat as well as
the dungeon generation. But one can also mix with other non-EvAdventure rooms (you will
just not be able to fight in them).
""" """
from copy import deepcopy from copy import deepcopy
from evennia import AttributeProperty, DefaultCharacter, DefaultRoom, TagProperty from evennia import DefaultCharacter, DefaultRoom
from evennia.utils.utils import inherits_from from evennia.utils.utils import inherits_from
CHAR_SYMBOL = "|w@|n"
CHAR_ALT_SYMBOL = "|w>|n"
ROOM_SYMBOL = "|bo|n"
LINK_COLOR = "|B"
_MAP_GRID = [ _MAP_GRID = [
[" ", " ", " ", " ", " "], [" ", " ", " ", " ", " "],
[" ", " ", " ", " ", " "], [" ", " ", " ", " ", " "],
@ -18,9 +27,9 @@ _MAP_GRID = [
[" ", " ", " ", " ", " "], [" ", " ", " ", " ", " "],
] ]
_EXIT_GRID_SHIFT = { _EXIT_GRID_SHIFT = {
"north": (0, 1, "|"), "north": (0, 1, "||"),
"east": (1, 0, "-"), "east": (1, 0, "-"),
"south": (0, -1, "|"), "south": (0, -1, "||"),
"west": (-1, 0, "-"), "west": (-1, 0, "-"),
"northeast": (1, 1, "/"), "northeast": (1, 1, "/"),
"southeast": (1, -1, "\\"), "southeast": (1, -1, "\\"),
@ -46,24 +55,28 @@ class EvAdventureRoom(DefaultRoom):
def get_display_header(self, looker, **kwargs): def get_display_header(self, looker, **kwargs):
""" """
Display the current location as a mini-map. Display the current location as a mini-map.
""" """
if not inherits_from(looker, DefaultCharacter): # make sure to not show make a map for users of screenreaders.
# we don't need a map for npcs/mobs # for optimization we also don't show it to npcs/mobs
if not inherits_from(looker, DefaultCharacter) or (
looker.account and looker.account.uses_screenreader()
):
return "" return ""
# build a map # build a map
map_grid = deepcopy(_MAP_GRID) map_grid = deepcopy(_MAP_GRID)
dx0, dy0 = 2, 2 dx0, dy0 = 2, 2
map_grid[dy0][dx0] = "|w@|n" map_grid[dy0][dx0] = CHAR_SYMBOL
for exi in self.exits: for exi in self.exits:
dx, dy, symbol = _EXIT_GRID_SHIFT.get(exi.key, (None, None, None)) dx, dy, symbol = _EXIT_GRID_SHIFT.get(exi.key, (None, None, None))
if symbol is None: if symbol is None:
# we have a non-cardinal direction to go to - mark us blue to indicate this # we have a non-cardinal direction to go to - indicate this
map_grid[dy0][dx0] = "|b>|n" map_grid[dy0][dx0] = CHAR_ALT_SYMBOL
continue continue
map_grid[dy0 + dy][dx0 + dx] = symbol map_grid[dy0 + dy][dx0 + dx] = f"{LINK_COLOR}{symbol}|n"
if exi.destination != self: if exi.destination != self:
map_grid[dy0 + dy + dy][dx0 + dx + dx] = "X" map_grid[dy0 + dy + dy][dx0 + dx + dx] = ROOM_SYMBOL
# Note that on the grid, dy is really going *downwards* (origo is # Note that on the grid, dy is really going *downwards* (origo is
# in the top left), so we need to reverse the order at the end to mirror it # in the top left), so we need to reverse the order at the end to mirror it

View file

@ -4,10 +4,17 @@ Helpers for testing evadventure modules.
""" """
from evennia.utils import create from evennia.utils import create
from ..characters import EvAdventureCharacter
from ..objects import EvAdventureObject
from ..rooms import EvAdventureRoom
from .. import enums from .. import enums
from ..characters import EvAdventureCharacter
from ..objects import (
EvAdventureArmor,
EvAdventureHelmet,
EvAdventureObject,
EvAdventureShield,
EvAdventureWeapon,
)
from ..rooms import EvAdventureRoom
class EvAdventureMixin: class EvAdventureMixin:
@ -23,27 +30,27 @@ class EvAdventureMixin:
EvAdventureCharacter, key="testchar", location=self.location EvAdventureCharacter, key="testchar", location=self.location
) )
self.helmet = create.create_object( self.helmet = create.create_object(
EvAdventureObject, EvAdventureHelmet,
key="helmet", key="helmet",
attributes=[("inventory_use_slot", enums.WieldLocation.HEAD), ("armor", 1)], attributes=[("inventory_use_slot", enums.WieldLocation.HEAD), ("armor", 1)],
) )
self.shield = create.create_object( self.shield = create.create_object(
EvAdventureObject, EvAdventureShield,
key="shield", key="shield",
attributes=[("inventory_use_slot", enums.WieldLocation.SHIELD_HAND), ("armor", 1)], attributes=[("inventory_use_slot", enums.WieldLocation.SHIELD_HAND), ("armor", 1)],
) )
self.armor = create.create_object( self.armor = create.create_object(
EvAdventureObject, EvAdventureArmor,
key="armor", key="armor",
attributes=[("inventory_use_slot", enums.WieldLocation.BODY), ("armor", 11)], attributes=[("inventory_use_slot", enums.WieldLocation.BODY), ("armor", 11)],
) )
self.weapon = create.create_object( self.weapon = create.create_object(
EvAdventureObject, EvAdventureWeapon,
key="weapon", key="weapon",
attributes=[("inventory_use_slot", enums.WieldLocation.WEAPON_HAND)], attributes=[("inventory_use_slot", enums.WieldLocation.WEAPON_HAND)],
) )
self.big_weapon = create.create_object( self.big_weapon = create.create_object(
EvAdventureObject, EvAdventureWeapon,
key="big_weapon", key="big_weapon",
attributes=[("inventory_use_slot", enums.WieldLocation.TWO_HANDS)], attributes=[("inventory_use_slot", enums.WieldLocation.TWO_HANDS)],
) )

View file

@ -10,7 +10,6 @@ from evennia.utils.test_resources import BaseEvenniaTest
from evennia.utils.utils import inherits_from from evennia.utils.utils import inherits_from
from .. import dungeon from .. import dungeon
from ..rooms import EvAdventureDungeonRoom
from .mixins import EvAdventureMixin from .mixins import EvAdventureMixin
@ -33,7 +32,7 @@ class TestDungeon(EvAdventureMixin, BaseEvenniaTest):
self.start_room = create_object(droomclass, key="bottom of well") self.start_room = create_object(droomclass, key="bottom of well")
self.assertEqual( self.assertEqual(
self.start_room.scripts.get("evadventure_startroom_resetter")[0].interval, -1 self.start_room.scripts.get("evadventure_dungeon_startroom_resetter")[0].interval, -1
) )
self.start_north = create_object( self.start_north = create_object(
dungeon.EvAdventureDungeonStartRoomExit, dungeon.EvAdventureDungeonStartRoomExit,
@ -71,7 +70,7 @@ class TestDungeon(EvAdventureMixin, BaseEvenniaTest):
# first go north, this should generate a new room # first go north, this should generate a new room
new_room_north = self._move_character("north") new_room_north = self._move_character("north")
self.assertNotEqual(self.start_room, new_room_north) self.assertNotEqual(self.start_room, new_room_north)
self.assertTrue(inherits_from(new_room_north, EvAdventureDungeonRoom)) self.assertTrue(inherits_from(new_room_north, dungeon.EvAdventureDungeonRoom))
# check if Orchestrator was created # check if Orchestrator was created
orchestrator = new_room_north.db.dungeon_orchestrator orchestrator = new_room_north.db.dungeon_orchestrator