forked from vantablack/vantaMOO
refactor character code structure
This commit is contained in:
parent
8a458b21b5
commit
08facf7d00
|
@ -23,8 +23,7 @@ from evennia.contrib.game_systems.clothing import ClothedCharacterCmdSet
|
|||
from evennia.contrib.game_systems.multidescer import CmdMultiDesc
|
||||
from evennia.contrib.grid import simpledoor
|
||||
from evennia.contrib.grid.ingame_map_display import MapDisplayCmdSet
|
||||
from lib.pronounsub import PronounAdminCommand
|
||||
from lib.pronounsub import PronounsCommand
|
||||
from lib.pronounsub.commands import *
|
||||
from lib.rpsystem.rpsystem import RPSystemCmdSet
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
from .pronounsub import PronounCharacter
|
||||
from .pronounsub import PronounsCommand
|
||||
from .pronounsub import PronounAdminCommand
|
||||
from .db import PronounDbScript
|
|
@ -0,0 +1,49 @@
|
|||
from .common import *
|
||||
|
||||
# This should be called before every use of a Character to make sure it's
|
||||
# initialized right.
|
||||
def object_init(character):
|
||||
if character.db.pronouns == None:
|
||||
character.db.pronouns = DEFAULT_CHARACTER_PRONOUNS[:]
|
||||
if character.db.pronoun_specs == None:
|
||||
character.db.pronoun_specs = []
|
||||
|
||||
def msg(character, text=None, from_obj=None, session=None, **kwargs):
|
||||
object_init(character)
|
||||
|
||||
"""
|
||||
Emits something to a session attached to the object.
|
||||
Overloads the default msg() implementation to include
|
||||
gender-aware markers in output.
|
||||
|
||||
Args:
|
||||
text (str or tuple, optional): The message to send. This
|
||||
is treated internally like any send-command, so its
|
||||
value can be a tuple if sending multiple arguments to
|
||||
the `text` oob command.
|
||||
from_obj (obj, optional): object that is sending. If
|
||||
given, at_msg_send will be called
|
||||
session (Session or list, optional): session or list of
|
||||
sessions to relay to, if any. If set, will
|
||||
force send regardless of MULTISESSION_MODE.
|
||||
Note:
|
||||
`at_msg_receive` will be called on this Object.
|
||||
All extra kwargs will be passed on to the protocol.
|
||||
|
||||
"""
|
||||
if text is None:
|
||||
super().msg(from_obj=from_obj, session=session, **kwargs)
|
||||
return
|
||||
|
||||
try:
|
||||
repl = lambda a: pronoun_repl(character, a)
|
||||
|
||||
if text and isinstance(text, tuple):
|
||||
text = (RE_GENDER_PRONOUN.sub(repl, text[0]), *text[1:])
|
||||
else:
|
||||
text = RE_GENDER_PRONOUN.sub(repl, text)
|
||||
except TypeError:
|
||||
pass
|
||||
except Exception as e:
|
||||
logger.log_trace(e)
|
||||
return (text, from_obj, session, kwargs)
|
|
@ -1,81 +1,5 @@
|
|||
"""
|
||||
Pronounsub
|
||||
|
||||
Griatch 2015
|
||||
Copyright (c) 2023 lunacb <lunacb@disroot.org>
|
||||
|
||||
This is a gender-aware Character class that allows people to set pronouns and
|
||||
use them in text.
|
||||
|
||||
Usage
|
||||
|
||||
When in use, messages can contain special tags to indicate pronouns gendered
|
||||
based on the one being addressed. Capitalization will be retained.
|
||||
|
||||
- `|s`, `|S`: Subjective form, like They
|
||||
- `|o`, `|O`: Objective form, like Them
|
||||
- `|p`, `|P`: Possessive form, like Their
|
||||
- `|a`, `|A`: Absolute Possessive form, like Theirs
|
||||
|
||||
For example,
|
||||
|
||||
```
|
||||
char.msg("%s falls on |p face with a thud." % char.key)
|
||||
"Tom falls on their face with a thud"
|
||||
```
|
||||
|
||||
To use, have DefaultCharacter inherit from this, or change
|
||||
setting.DEFAULT_CHARACTER to point to this class.
|
||||
|
||||
The `pronouns` command is used to set pronouns. It needs to be added to the
|
||||
default cmdset before it becomes available.
|
||||
|
||||
"""
|
||||
|
||||
import random
|
||||
|
||||
from evennia import Command, DefaultCharacter
|
||||
from evennia import InterruptCommand
|
||||
from evennia.utils import logger
|
||||
from evennia.utils.create import create_script
|
||||
from evennia.utils.search import search_script
|
||||
from .consts import *
|
||||
|
||||
# in-game command for setting the gender
|
||||
|
||||
def parse_specific_pronoun(pronoun):
|
||||
specific = [ p.strip() for p in pronoun.split(",") ]
|
||||
if len(specific) != len(PRONOUN_FORMS):
|
||||
return None
|
||||
|
||||
new = {}
|
||||
for i in range(len(specific)):
|
||||
new[PRONOUN_FORMS[i]] = specific[i]
|
||||
|
||||
return new
|
||||
|
||||
def get_pronoun_list():
|
||||
search = search_script("pronoun_db")
|
||||
if not any(search):
|
||||
script = create_script("lib.pronounsub.PronounDbScript", key="pronoun_db")
|
||||
else:
|
||||
script = search[0]
|
||||
|
||||
return script.db.pronouns
|
||||
|
||||
def specific_pronoun_from_character(character, caller=None):
|
||||
pronoun_list = get_pronoun_list()[:]
|
||||
if caller != None:
|
||||
# TODO: reorder
|
||||
pronoun_list += caller.db.pronoun_specs
|
||||
for pronoun in pronoun_list:
|
||||
if character in pronoun.values():
|
||||
return pronoun
|
||||
|
||||
return None
|
||||
|
||||
def stringify_specific_pronoun(spec):
|
||||
return ",".join([ spec[form] for form in PRONOUN_FORMS ])
|
||||
from .common import *
|
||||
from .character import object_init
|
||||
|
||||
class PronounAdminCommand(Command):
|
||||
"""
|
||||
|
@ -221,7 +145,7 @@ class PronounsCommand(Command):
|
|||
|
||||
def parse(self):
|
||||
caller = self.caller
|
||||
caller.pronoun_object_init()
|
||||
object_init(caller)
|
||||
|
||||
args = self.args.strip().lower().split()
|
||||
if len(args) == 1:
|
||||
|
@ -254,7 +178,7 @@ class PronounsCommand(Command):
|
|||
|
||||
def func(self):
|
||||
caller = self.caller
|
||||
caller.pronoun_object_init()
|
||||
object_init(caller)
|
||||
|
||||
command = self.args[0]
|
||||
|
||||
|
@ -275,10 +199,10 @@ class PronounsCommand(Command):
|
|||
"details. |/")
|
||||
|
||||
caller.db.pronouns = pronouns
|
||||
caller.msg(f"Your pronouns have been set to {caller._stringify_pronouns()}.")
|
||||
caller.msg(f"Your pronouns have been set to {stringify_pronouns(caller)}.")
|
||||
|
||||
case "get":
|
||||
caller.msg(f"Your pronouns are {caller._stringify_pronouns()}.")
|
||||
caller.msg(f"Your pronouns are {stringify_pronouns(caller)}.")
|
||||
|
||||
case "list_known":
|
||||
caller.msg("Known user-defined pronouns:")
|
||||
|
@ -299,101 +223,3 @@ class PronounsCommand(Command):
|
|||
if pronoun in caller.db.pronoun_specs:
|
||||
caller.db.pronoun_specs.remove(pronoun)
|
||||
self.caller.msg(f"Remobed the pronoun {stringify_specific_pronoun(pronoun)}.")
|
||||
|
||||
class PronounCharacter(DefaultCharacter):
|
||||
"""
|
||||
This is a Character class aware of gender.
|
||||
|
||||
"""
|
||||
|
||||
# This should be called before every use of a Character to make sure it's
|
||||
# initialized right.
|
||||
def pronoun_object_init(self):
|
||||
if self.db.pronouns == None:
|
||||
self.db.pronouns = DEFAULT_CHARACTER_PRONOUNS[:]
|
||||
if self.db.pronoun_specs == None:
|
||||
self.db.pronoun_specs = []
|
||||
|
||||
def at_object_creation(self):
|
||||
"""
|
||||
Called once when the object is created.
|
||||
"""
|
||||
super().at_object_creation()
|
||||
self.pronoun_object_init()
|
||||
|
||||
def _stringify_pronouns(self):
|
||||
pronouns = self.attributes.get("pronouns", default=DEFAULT_CHARACTER_PRONOUNS[:])
|
||||
return "/".join(pronouns)
|
||||
|
||||
def _get_pronoun(self, regex_match):
|
||||
"""
|
||||
Get pronoun from the pronoun marker in the text. This is used as
|
||||
the callable for the re.sub function.
|
||||
|
||||
Args:
|
||||
regex_match (MatchObject): the regular expression match.
|
||||
|
||||
Notes:
|
||||
- `|s`, `|S`: Subjective form, like They
|
||||
- `|o`, `|O`: Objective form, like Them
|
||||
- `|p`, `|P`: Possessive form, like Their
|
||||
- `|a`, `|A`: Absolute Possessive form, like Theirs
|
||||
|
||||
"""
|
||||
typ = regex_match.group()[1] # "s", "O" etc
|
||||
dup_specifics = []
|
||||
for pronoun in self.attributes.get("pronouns", default=DEFAULT_CHARACTER_PRONOUNS[:]):
|
||||
specific = specific_pronoun_from_character(pronoun, self)
|
||||
if specific != None:
|
||||
dup_specifics.append(specific)
|
||||
|
||||
specifics = []
|
||||
for s in dup_specifics:
|
||||
if not s in specifics:
|
||||
specifics.append(s)
|
||||
|
||||
if len(specifics) == 0:
|
||||
choice = DEFAULT_SPECIFIC_NEUTRAL_PRONOUNS
|
||||
else:
|
||||
choice = random.choice(specifics)
|
||||
|
||||
pronoun = choice[typ.lower()]
|
||||
return pronoun.capitalize() if typ.isupper() else pronoun
|
||||
|
||||
def msg(self, text=None, from_obj=None, session=None, **kwargs):
|
||||
self.pronoun_object_init()
|
||||
|
||||
"""
|
||||
Emits something to a session attached to the object.
|
||||
Overloads the default msg() implementation to include
|
||||
gender-aware markers in output.
|
||||
|
||||
Args:
|
||||
text (str or tuple, optional): The message to send. This
|
||||
is treated internally like any send-command, so its
|
||||
value can be a tuple if sending multiple arguments to
|
||||
the `text` oob command.
|
||||
from_obj (obj, optional): object that is sending. If
|
||||
given, at_msg_send will be called
|
||||
session (Session or list, optional): session or list of
|
||||
sessions to relay to, if any. If set, will
|
||||
force send regardless of MULTISESSION_MODE.
|
||||
Notes:
|
||||
`at_msg_receive` will be called on this Object.
|
||||
All extra kwargs will be passed on to the protocol.
|
||||
|
||||
"""
|
||||
if text is None:
|
||||
super().msg(from_obj=from_obj, session=session, **kwargs)
|
||||
return
|
||||
|
||||
try:
|
||||
if text and isinstance(text, tuple):
|
||||
text = (RE_GENDER_PRONOUN.sub(self._get_pronoun, text[0]), *text[1:])
|
||||
else:
|
||||
text = RE_GENDER_PRONOUN.sub(self._get_pronoun, text)
|
||||
except TypeError:
|
||||
pass
|
||||
except Exception as e:
|
||||
logger.log_trace(e)
|
||||
super().msg(text, from_obj=from_obj, session=session, **kwargs)
|
|
@ -0,0 +1,137 @@
|
|||
"""
|
||||
Pronounsub
|
||||
|
||||
Griatch 2015
|
||||
Copyright (c) 2023 lunacb <lunacb@disroot.org>
|
||||
|
||||
This is a gender-aware Character class that allows people to set pronouns and
|
||||
use them in text.
|
||||
|
||||
Usage
|
||||
|
||||
When in use, messages can contain special tags to indicate pronouns gendered
|
||||
based on the one being addressed. Capitalization will be retained.
|
||||
|
||||
- `|s`, `|S`: Subjective form, like They
|
||||
- `|o`, `|O`: Objective form, like Them
|
||||
- `|p`, `|P`: Possessive form, like Their
|
||||
- `|a`, `|A`: Absolute Possessive form, like Theirs
|
||||
|
||||
For example,
|
||||
|
||||
```
|
||||
char.msg("%s falls on |p face with a thud." % char.key)
|
||||
"Tom falls on their face with a thud"
|
||||
```
|
||||
|
||||
To use, have DefaultCharacter inherit from this, or change
|
||||
setting.DEFAULT_CHARACTER to point to this class.
|
||||
|
||||
The `pronouns` command is used to set pronouns. It needs to be added to the
|
||||
default cmdset before it becomes available.
|
||||
|
||||
"""
|
||||
|
||||
import copy
|
||||
import random
|
||||
import re
|
||||
|
||||
from evennia import Command, DefaultCharacter
|
||||
from evennia import DefaultScript
|
||||
from evennia import InterruptCommand
|
||||
from evennia.utils import logger
|
||||
from evennia.utils.create import create_script
|
||||
from evennia.utils.search import search_script
|
||||
|
||||
class PronounDbScript(DefaultScript):
|
||||
def at_script_creation(self):
|
||||
self.db.pronouns = copy.deepcopy(DEFAULT_SPECIFIC_PRONOUNS)
|
||||
|
||||
DEFAULT_SPECIFIC_NEUTRAL_PRONOUNS = {"s": "they", "o": "them", "p": "their", "a": "theirs"}
|
||||
|
||||
DEFAULT_SPECIFIC_PRONOUNS = [
|
||||
{"s": "he", "o": "him", "p": "his", "a": "his"},
|
||||
{"s": "she", "o": "her", "p": "her", "a": "hers"},
|
||||
{"s": "it", "o": "it", "p": "its", "a": "its"},
|
||||
{"s": "they", "o": "them", "p": "their", "a": "theirs"}
|
||||
]
|
||||
|
||||
DEFAULT_CHARACTER_PRONOUNS = [ "they", "them" ]
|
||||
|
||||
PRONOUN_FORMS = [ "s", "o", "p", "a" ]
|
||||
|
||||
RE_GENDER_PRONOUN = re.compile(r"(?<!\|)\|(?!\|)[sSoOpPaA]")
|
||||
|
||||
# in-game command for setting the gender
|
||||
|
||||
def parse_specific_pronoun(pronoun):
|
||||
specific = [ p.strip() for p in pronoun.split(",") ]
|
||||
if len(specific) != len(PRONOUN_FORMS):
|
||||
return None
|
||||
|
||||
new = {}
|
||||
for i in range(len(specific)):
|
||||
new[PRONOUN_FORMS[i]] = specific[i]
|
||||
|
||||
return new
|
||||
|
||||
def get_pronoun_list():
|
||||
search = search_script("pronoun_db")
|
||||
if not any(search):
|
||||
script = create_script("lib.pronounsub.PronounDbScript", key="pronoun_db")
|
||||
else:
|
||||
script = search[0]
|
||||
|
||||
return script.db.pronouns
|
||||
|
||||
def specific_pronoun_from_character(character, caller=None):
|
||||
pronoun_list = get_pronoun_list()[:]
|
||||
if caller != None:
|
||||
pronoun_list = caller.db.pronoun_specs + pronoun_list
|
||||
for pronoun in pronoun_list:
|
||||
if character in pronoun.values():
|
||||
return pronoun
|
||||
|
||||
return None
|
||||
|
||||
def stringify_specific_pronoun(spec):
|
||||
return ",".join([ spec[form] for form in PRONOUN_FORMS ])
|
||||
|
||||
def stringify_pronouns(character):
|
||||
pronouns = character.attributes.get("pronouns", default=DEFAULT_CHARACTER_PRONOUNS[:])
|
||||
return "/".join(pronouns)
|
||||
|
||||
def pronoun_repl(character, regex_match):
|
||||
"""
|
||||
Get pronoun from the pronoun marker in the text. This is used as
|
||||
the callable for the re.sub function.
|
||||
|
||||
Args:
|
||||
regex_match (MatchObject): the regular expression match.
|
||||
|
||||
Notes:
|
||||
- `|s`, `|S`: Subjective form, like They
|
||||
- `|o`, `|O`: Objective form, like Them
|
||||
- `|p`, `|P`: Possessive form, like Their
|
||||
- `|a`, `|A`: Absolute Possessive form, like Theirs
|
||||
|
||||
"""
|
||||
typ = regex_match.group()[1] # "s", "O" etc
|
||||
dup_specifics = []
|
||||
for pronoun in character.attributes.get("pronouns", default=DEFAULT_CHARACTER_PRONOUNS[:]):
|
||||
specific = specific_pronoun_from_character(pronoun, character)
|
||||
if specific != None:
|
||||
dup_specifics.append(specific)
|
||||
|
||||
specifics = []
|
||||
for s in dup_specifics:
|
||||
if not s in specifics:
|
||||
specifics.append(s)
|
||||
|
||||
if len(specifics) == 0:
|
||||
choice = DEFAULT_SPECIFIC_NEUTRAL_PRONOUNS
|
||||
else:
|
||||
choice = random.choice(specifics)
|
||||
|
||||
pronoun = choice[typ.lower()]
|
||||
return pronoun.capitalize() if typ.isupper() else pronoun
|
|
@ -1,16 +0,0 @@
|
|||
import re
|
||||
|
||||
DEFAULT_SPECIFIC_NEUTRAL_PRONOUNS = {"s": "they", "o": "them", "p": "their", "a": "theirs"}
|
||||
|
||||
DEFAULT_SPECIFIC_PRONOUNS = [
|
||||
{"s": "he", "o": "him", "p": "his", "a": "his"},
|
||||
{"s": "she", "o": "her", "p": "her", "a": "hers"},
|
||||
{"s": "it", "o": "it", "p": "its", "a": "its"},
|
||||
{"s": "they", "o": "them", "p": "their", "a": "theirs"}
|
||||
]
|
||||
|
||||
DEFAULT_CHARACTER_PRONOUNS = [ "they", "them" ]
|
||||
|
||||
PRONOUN_FORMS = [ "s", "o", "p", "a" ]
|
||||
|
||||
RE_GENDER_PRONOUN = re.compile(r"(?<!\|)\|(?!\|)[sSoOpPaA]")
|
|
@ -1,8 +0,0 @@
|
|||
import copy
|
||||
|
||||
from evennia import DefaultScript
|
||||
from .consts import *
|
||||
|
||||
class PronounDbScript(DefaultScript):
|
||||
def at_script_creation(self):
|
||||
self.db.pronouns = copy.deepcopy(DEFAULT_SPECIFIC_PRONOUNS)
|
|
@ -157,8 +157,9 @@ from django.conf import settings
|
|||
|
||||
from evennia.commands.cmdset import CmdSet
|
||||
from evennia.commands.command import Command
|
||||
from evennia.contrib.game_systems.clothing import ClothedCharacter
|
||||
from evennia.objects.models import ObjectDB
|
||||
from evennia.objects.objects import DefaultCharacter, DefaultObject
|
||||
from evennia.objects.objects import DefaultObject
|
||||
from evennia.utils import ansi, logger
|
||||
from evennia.utils.utils import (
|
||||
iter_to_str,
|
||||
|
@ -1606,7 +1607,7 @@ class ContribRPRoom(ContribRPObject):
|
|||
pass
|
||||
|
||||
|
||||
class ContribRPCharacter(DefaultCharacter, ContribRPObject):
|
||||
class ContribRPCharacter(ClothedCharacter, ContribRPObject):
|
||||
"""
|
||||
This is a character class that has poses, sdesc and recog.
|
||||
"""
|
||||
|
|
|
@ -8,14 +8,17 @@ creation commands.
|
|||
|
||||
"""
|
||||
from lib.rpsystem import ContribRPCharacter
|
||||
from lib.pronounsub import PronounCharacter
|
||||
from evennia.contrib.game_systems.clothing import ClothedCharacter
|
||||
|
||||
from lib.pronounsub import character as pronounsub
|
||||
|
||||
# rpsystem
|
||||
class Character(ContribRPCharacter, ClothedCharacter, PronounCharacter):
|
||||
class Character(ContribRPCharacter):
|
||||
def at_object_creation(self):
|
||||
pronounsub.object_init(self)
|
||||
|
||||
super().at_object_creation()
|
||||
|
||||
def msg(self, text=None, from_obj=None, session=None, **kwargs):
|
||||
# TODO: Don't do this. See https://git.disroot.org/vantablack/vantaMOO/issues/29
|
||||
text, from_obj, session, kwargs = pronounsub.msg(self, text, from_obj, session, **kwargs)
|
||||
|
||||
super().msg(text, from_obj, session, **kwargs)
|
||||
|
|
Loading…
Reference in New Issue