mirror of
https://github.com/evennia/evennia.git
synced 2026-04-02 05:57:16 +02:00
commit
be8cf70621
15 changed files with 188 additions and 79 deletions
12
Dockerfile
12
Dockerfile
|
|
@ -5,11 +5,11 @@
|
|||
# install `docker` (http://docker.com)
|
||||
#
|
||||
# Usage:
|
||||
# cd to a folder where you want your game data to be (or where it already is).
|
||||
# cd to a folder where you want your game data to be (or where it already is).
|
||||
#
|
||||
# docker run -it -p 4000:4000 -p 4001:4001 -p 4005:4005 -v $PWD:/usr/src/game evennia/evennia
|
||||
#
|
||||
# (If your OS does not support $PWD, replace it with the full path to your current
|
||||
#
|
||||
# (If your OS does not support $PWD, replace it with the full path to your current
|
||||
# folder).
|
||||
#
|
||||
# You will end up in a shell where the `evennia` command is available. From here you
|
||||
|
|
@ -30,10 +30,10 @@ RUN apk update && apk add python py-pip python-dev py-setuptools gcc musl-dev jp
|
|||
ADD . /usr/src/evennia
|
||||
|
||||
# install dependencies
|
||||
RUN pip install -e /usr/src/evennia --trusted-host pypi.python.org
|
||||
RUN pip install --upgrade pip && pip install /usr/src/evennia --trusted-host pypi.python.org
|
||||
|
||||
# add the game source when rebuilding a new docker image from inside
|
||||
# a game dir
|
||||
# a game dir
|
||||
ONBUILD ADD . /usr/src/game
|
||||
|
||||
# make the game source hierarchy persistent with a named volume.
|
||||
|
|
@ -48,7 +48,7 @@ WORKDIR /usr/src/game
|
|||
ENV PS1 "evennia|docker \w $ "
|
||||
|
||||
# startup a shell when we start the container
|
||||
ENTRYPOINT ["bash"]
|
||||
ENTRYPOINT bash -c "source /usr/src/evennia/bin/unix/evennia-docker-start.sh"
|
||||
|
||||
# expose the telnet, webserver and websocket client ports
|
||||
EXPOSE 4000 4001 4005
|
||||
|
|
|
|||
13
bin/unix/evennia-docker-start.sh
Normal file
13
bin/unix/evennia-docker-start.sh
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#! /bin/bash
|
||||
|
||||
# called by the Dockerfile to start the server in docker mode
|
||||
|
||||
# remove leftover .pid files (such as from when dropping the container)
|
||||
rm /usr/src/game/server/*.pid >& /dev/null || true
|
||||
|
||||
# start evennia server; log to server.log but also output to stdout so it can
|
||||
# be viewed with docker-compose logs
|
||||
exec 3>&1; evennia start 2>&1 1>&3 | tee /usr/src/game/server/logs/server.log; exec 3>&-
|
||||
|
||||
# start a shell to keep the container running
|
||||
bash
|
||||
|
|
@ -301,7 +301,7 @@ class CmdDelAccount(COMMAND_DEFAULT_CLASS):
|
|||
|
||||
# one single match
|
||||
|
||||
account = accounts.pop()
|
||||
account = accounts.first()
|
||||
|
||||
if not account.access(caller, 'delete'):
|
||||
string = "You don't have the permissions to delete that account."
|
||||
|
|
|
|||
|
|
@ -1087,7 +1087,7 @@ class CmdSetHome(CmdLink):
|
|||
set an object's home location
|
||||
|
||||
Usage:
|
||||
@home <obj> [= <home_location>]
|
||||
@sethome <obj> [= <home_location>]
|
||||
|
||||
The "home" location is a "safety" location for objects; they
|
||||
will be moved there if their current location ceases to exist. All
|
||||
|
|
@ -1098,13 +1098,13 @@ class CmdSetHome(CmdLink):
|
|||
"""
|
||||
|
||||
key = "@sethome"
|
||||
locks = "cmd:perm(@home) or perm(Builder)"
|
||||
locks = "cmd:perm(@sethome) or perm(Builder)"
|
||||
help_category = "Building"
|
||||
|
||||
def func(self):
|
||||
"""implement the command"""
|
||||
if not self.args:
|
||||
string = "Usage: @home <obj> [= <home_location>]"
|
||||
string = "Usage: @sethome <obj> [= <home_location>]"
|
||||
self.caller.msg(string)
|
||||
return
|
||||
|
||||
|
|
|
|||
|
|
@ -53,10 +53,11 @@ class ChannelAdmin(admin.ModelAdmin):
|
|||
list_display = ('id', 'db_key', 'db_lock_storage', "subscriptions")
|
||||
list_display_links = ("id", 'db_key')
|
||||
ordering = ["db_key"]
|
||||
search_fields = ['id', 'db_key', 'db_aliases']
|
||||
search_fields = ['id', 'db_key', 'db_tags__db_key']
|
||||
save_as = True
|
||||
save_on_top = True
|
||||
list_select_related = True
|
||||
raw_id_fields = ('db_object_subscriptions', 'db_account_subscriptions',)
|
||||
fieldsets = (
|
||||
(None, {'fields': (('db_key',), 'db_lock_storage', 'db_account_subscriptions', 'db_object_subscriptions')}),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -21,30 +21,30 @@ in the game in various ways:
|
|||
Usage:
|
||||
|
||||
```python
|
||||
from evennia.contrib import rplanguages
|
||||
from evennia.contrib import rplanguage
|
||||
|
||||
# need to be done once, here we create the "default" lang
|
||||
rplanguages.add_language()
|
||||
rplanguage.add_language()
|
||||
|
||||
say = "This is me talking."
|
||||
whisper = "This is me whispering.
|
||||
|
||||
print rplanguages.obfuscate_language(say, level=0.0)
|
||||
print rplanguage.obfuscate_language(say, level=0.0)
|
||||
<<< "This is me talking."
|
||||
print rplanguages.obfuscate_language(say, level=0.5)
|
||||
print rplanguage.obfuscate_language(say, level=0.5)
|
||||
<<< "This is me byngyry."
|
||||
print rplanguages.obfuscate_language(say, level=1.0)
|
||||
print rplanguage.obfuscate_language(say, level=1.0)
|
||||
<<< "Daly ly sy byngyry."
|
||||
|
||||
result = rplanguages.obfuscate_whisper(whisper, level=0.0)
|
||||
result = rplanguage.obfuscate_whisper(whisper, level=0.0)
|
||||
<<< "This is me whispering"
|
||||
result = rplanguages.obfuscate_whisper(whisper, level=0.2)
|
||||
result = rplanguage.obfuscate_whisper(whisper, level=0.2)
|
||||
<<< "This is m- whisp-ring"
|
||||
result = rplanguages.obfuscate_whisper(whisper, level=0.5)
|
||||
result = rplanguage.obfuscate_whisper(whisper, level=0.5)
|
||||
<<< "---s -s -- ---s------"
|
||||
result = rplanguages.obfuscate_whisper(whisper, level=0.7)
|
||||
result = rplanguage.obfuscate_whisper(whisper, level=0.7)
|
||||
<<< "---- -- -- ----------"
|
||||
result = rplanguages.obfuscate_whisper(whisper, level=1.0)
|
||||
result = rplanguage.obfuscate_whisper(whisper, level=1.0)
|
||||
<<< "..."
|
||||
|
||||
```
|
||||
|
|
@ -71,7 +71,7 @@ Usage:
|
|||
manual_translations = {"the":"y'e", "we":"uyi", "she":"semi", "he":"emi",
|
||||
"you": "do", 'me':'mi','i':'me', 'be':"hy'e", 'and':'y'}
|
||||
|
||||
rplanguages.add_language(key="elvish", phonemes=phonemes, grammar=grammar,
|
||||
rplanguage.add_language(key="elvish", phonemes=phonemes, grammar=grammar,
|
||||
word_length_variance=word_length_variance,
|
||||
noun_postfix=noun_postfix, vowels=vowels,
|
||||
manual_translations=manual_translations
|
||||
|
|
@ -96,6 +96,7 @@ import re
|
|||
from random import choice, randint
|
||||
from collections import defaultdict
|
||||
from evennia import DefaultScript
|
||||
from evennia.utils import logger
|
||||
|
||||
|
||||
#------------------------------------------------------------
|
||||
|
|
@ -105,21 +106,26 @@ from evennia import DefaultScript
|
|||
#------------------------------------------------------------
|
||||
|
||||
# default language grammar
|
||||
_PHONEMES = "ea oh ae aa eh ah ao aw ai er ey ow ia ih iy oy ua uh uw a e i u y p b t d f v t dh s z sh zh ch jh k ng g m n l r w"
|
||||
_PHONEMES = "ea oh ae aa eh ah ao aw ai er ey ow ia ih iy oy ua uh uw a e i u y p b t d f v t dh " \
|
||||
"s z sh zh ch jh k ng g m n l r w"
|
||||
_VOWELS = "eaoiuy"
|
||||
# these must be able to be constructed from phonemes (so for example,
|
||||
# if you have v here, there must exixt at least one single-character
|
||||
# if you have v here, there must exist at least one single-character
|
||||
# vowel phoneme defined above)
|
||||
_GRAMMAR = "v cv vc cvv vcc vcv cvcc vccv cvccv cvcvcc cvccvcv vccvccvc cvcvccvv cvcvcvcvv"
|
||||
|
||||
_RE_FLAGS = re.MULTILINE + re.IGNORECASE + re.UNICODE
|
||||
_RE_GRAMMAR = re.compile(r"vv|cc|v|c", _RE_FLAGS)
|
||||
_RE_WORD = re.compile(r'\w+', _RE_FLAGS)
|
||||
_RE_EXTRA_CHARS = re.compile(r'\s+(?=\W)|[,.?;](?=[,.?;]|\s+[,.?;])', _RE_FLAGS)
|
||||
|
||||
|
||||
class LanguageExistsError(Exception):
|
||||
message = "Language is already created. Re-adding it will re-build" \
|
||||
" its dictionary map. Use 'force=True' keyword if you are sure."
|
||||
class LanguageError(RuntimeError):
|
||||
pass
|
||||
|
||||
|
||||
class LanguageExistsError(LanguageError):
|
||||
pass
|
||||
|
||||
|
||||
class LanguageHandler(DefaultScript):
|
||||
|
|
@ -156,8 +162,11 @@ class LanguageHandler(DefaultScript):
|
|||
self.db.language_storage = {}
|
||||
|
||||
def add(self, key="default", phonemes=_PHONEMES,
|
||||
grammar=_GRAMMAR, word_length_variance=0, noun_prefix="",
|
||||
noun_postfix="", vowels=_VOWELS, manual_translations=None,
|
||||
grammar=_GRAMMAR, word_length_variance=0,
|
||||
noun_translate=False,
|
||||
noun_prefix="",
|
||||
noun_postfix="",
|
||||
vowels=_VOWELS, manual_translations=None,
|
||||
auto_translations=None, force=False):
|
||||
"""
|
||||
Add a new language. Note that you generally only need to do
|
||||
|
|
@ -170,14 +179,21 @@ class LanguageHandler(DefaultScript):
|
|||
will be used as an identifier for the language so it
|
||||
should be short and unique.
|
||||
phonemes (str, optional): Space-separated string of all allowed
|
||||
phonemes in this language.
|
||||
phonemes in this language. If either of the base phonemes
|
||||
(c, v, cc, vv) are present in the grammar, the phoneme list must
|
||||
at least include one example of each.
|
||||
grammar (str): All allowed consonant (c) and vowel (v) combinations
|
||||
allowed to build up words. For example cvv would be a consonant
|
||||
followed by two vowels (would allow for a word like 'die').
|
||||
allowed to build up words. Grammars are broken into the base phonemes
|
||||
(c, v, cc, vv) prioritizing the longer bases. So cvv would be a
|
||||
the c + vv (would allow for a word like 'die' whereas
|
||||
cvcvccc would be c+v+c+v+cc+c (a word like 'galosch').
|
||||
word_length_variance (real): The variation of length of words.
|
||||
0 means a minimal variance, higher variance may mean words
|
||||
have wildly varying length; this strongly affects how the
|
||||
language "looks".
|
||||
noun_translate (bool, optional): If a proper noun, identified as a
|
||||
capitalized word, should be translated or not. By default they
|
||||
will not, allowing for e.g. the names of characters to be understandable.
|
||||
noun_prefix (str, optional): A prefix to go before every noun
|
||||
in this language (if any).
|
||||
noun_postfix (str, optuonal): A postfix to go after every noun
|
||||
|
|
@ -213,21 +229,28 @@ class LanguageHandler(DefaultScript):
|
|||
|
||||
"""
|
||||
if key in self.db.language_storage and not force:
|
||||
raise LanguageExistsError
|
||||
|
||||
# allowed grammar are grouped by length
|
||||
gramdict = defaultdict(list)
|
||||
for gram in grammar.split():
|
||||
gramdict[len(gram)].append(gram)
|
||||
grammar = dict(gramdict)
|
||||
raise LanguageExistsError(
|
||||
"Language is already created. Re-adding it will re-build"
|
||||
" its dictionary map. Use 'force=True' keyword if you are sure.")
|
||||
|
||||
# create grammar_component->phoneme mapping
|
||||
# {"vv": ["ea", "oh", ...], ...}
|
||||
grammar2phonemes = defaultdict(list)
|
||||
for phoneme in phonemes.split():
|
||||
if re.search("\W", phoneme):
|
||||
raise LanguageError("The phoneme '%s' contains an invalid character" % phoneme)
|
||||
gram = "".join(["v" if char in vowels else "c" for char in phoneme])
|
||||
grammar2phonemes[gram].append(phoneme)
|
||||
|
||||
# allowed grammar are grouped by length
|
||||
gramdict = defaultdict(list)
|
||||
for gram in grammar.split():
|
||||
if re.search("\W|(!=[cv])", gram):
|
||||
raise LanguageError("The grammar '%s' is invalid (only 'c' and 'v' are allowed)" % gram)
|
||||
gramdict[len(gram)].append(gram)
|
||||
grammar = dict(gramdict)
|
||||
|
||||
|
||||
# create automatic translation
|
||||
translation = {}
|
||||
|
||||
|
|
@ -261,6 +284,7 @@ class LanguageHandler(DefaultScript):
|
|||
"grammar": grammar,
|
||||
"grammar2phonemes": dict(grammar2phonemes),
|
||||
"word_length_variance": word_length_variance,
|
||||
"noun_translate": noun_translate,
|
||||
"noun_prefix": noun_prefix,
|
||||
"noun_postfix": noun_postfix}
|
||||
self.db.language_storage[key] = storage
|
||||
|
|
@ -282,34 +306,63 @@ class LanguageHandler(DefaultScript):
|
|||
"""
|
||||
word = match.group()
|
||||
lword = len(word)
|
||||
|
||||
if len(word) <= self.level:
|
||||
# below level. Don't translate
|
||||
new_word = word
|
||||
else:
|
||||
# translate the word
|
||||
# try to translate the word from dictionary
|
||||
new_word = self.language["translation"].get(word.lower(), "")
|
||||
if not new_word:
|
||||
if word.istitle():
|
||||
# capitalized word we don't have a translation for -
|
||||
# treat as a name (don't translate)
|
||||
new_word = "%s%s%s" % (self.language["noun_prefix"], word, self.language["noun_postfix"])
|
||||
else:
|
||||
# make up translation on the fly. Length can
|
||||
# vary from un-translated word.
|
||||
wlen = max(0, lword + sum(randint(-1, 1) for i
|
||||
in range(self.language["word_length_variance"])))
|
||||
grammar = self.language["grammar"]
|
||||
if wlen not in grammar:
|
||||
# no dictionary translation. Generate one
|
||||
|
||||
# find out what preceeded this word
|
||||
wpos = match.start()
|
||||
preceeding = match.string[:wpos].strip()
|
||||
start_sentence = preceeding.endswith(".") or not preceeding
|
||||
|
||||
# make up translation on the fly. Length can
|
||||
# vary from un-translated word.
|
||||
wlen = max(0, lword + sum(randint(-1, 1) for i
|
||||
in range(self.language["word_length_variance"])))
|
||||
grammar = self.language["grammar"]
|
||||
if wlen not in grammar:
|
||||
if randint(0, 1) == 0:
|
||||
# this word has no direct translation!
|
||||
return ""
|
||||
wlen = 0
|
||||
new_word = ''
|
||||
else:
|
||||
# use random word length
|
||||
wlen = choice(grammar.keys())
|
||||
|
||||
if wlen:
|
||||
structure = choice(grammar[wlen])
|
||||
grammar2phonemes = self.language["grammar2phonemes"]
|
||||
for match in _RE_GRAMMAR.finditer(structure):
|
||||
# there are only four combinations: vv,cc,c,v
|
||||
new_word += choice(grammar2phonemes[match.group()])
|
||||
if word.istitle():
|
||||
# capitalize words the same way
|
||||
new_word = new_word.capitalize()
|
||||
try:
|
||||
new_word += choice(grammar2phonemes[match.group()])
|
||||
except KeyError:
|
||||
logger.log_trace("You need to supply at least one example of each of "
|
||||
"the four base phonemes (c, v, cc, vv)")
|
||||
# abort translation here
|
||||
new_word = ''
|
||||
break
|
||||
|
||||
if word.istitle():
|
||||
title_word = ''
|
||||
if not start_sentence and not self.language.get("noun_translate", False):
|
||||
# don't translate what we identify as proper nouns (names)
|
||||
title_word = word
|
||||
elif new_word:
|
||||
title_word = new_word
|
||||
|
||||
if title_word:
|
||||
# Regardless of if we translate or not, we will add the custom prefix/postfixes
|
||||
new_word = "%s%s%s" % (self.language["noun_prefix"],
|
||||
title_word.capitalize(),
|
||||
self.language["noun_postfix"])
|
||||
|
||||
if len(word) > 1 and word.isupper():
|
||||
# keep LOUD words loud also when translated
|
||||
new_word = new_word.upper()
|
||||
|
|
@ -341,7 +394,9 @@ class LanguageHandler(DefaultScript):
|
|||
|
||||
# configuring the translation
|
||||
self.level = int(10 * (1.0 - max(0, min(level, 1.0))))
|
||||
return _RE_WORD.sub(self._translate_sub, text)
|
||||
translation = _RE_WORD.sub(self._translate_sub, text)
|
||||
# the substitution may create too long empty spaces, remove those
|
||||
return _RE_EXTRA_CHARS.sub("", translation)
|
||||
|
||||
|
||||
# Language access functions
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ from evennia.contrib import rplanguage
|
|||
mtrans = {"testing": "1", "is": "2", "a": "3", "human": "4"}
|
||||
atrans = ["An", "automated", "advantageous", "repeatable", "faster"]
|
||||
|
||||
text = "Automated testing is advantageous for a number of reasons:" \
|
||||
text = "Automated testing is advantageous for a number of reasons: " \
|
||||
"tests may be executed Continuously without the need for human " \
|
||||
"intervention, They are easily repeatable, and often faster."
|
||||
|
||||
|
|
@ -33,6 +33,11 @@ class TestLanguage(EvenniaTest):
|
|||
manual_translations=mtrans,
|
||||
auto_translations=atrans,
|
||||
force=True)
|
||||
rplanguage.add_language(key="binary",
|
||||
phonemes="oo ii a ck w b d t",
|
||||
grammar="cvvv cvv cvvcv cvvcvv cvvvc cvvvcvv cvvc",
|
||||
noun_prefix='beep-',
|
||||
word_length_variance=4)
|
||||
|
||||
def tearDown(self):
|
||||
super(TestLanguage, self).tearDown()
|
||||
|
|
@ -44,22 +49,36 @@ class TestLanguage(EvenniaTest):
|
|||
self.assertEqual(result0, text)
|
||||
result1 = rplanguage.obfuscate_language(text, level=1.0, language="testlang")
|
||||
result2 = rplanguage.obfuscate_language(text, level=1.0, language="testlang")
|
||||
result3 = rplanguage.obfuscate_language(text, level=1.0, language='binary')
|
||||
|
||||
self.assertNotEqual(result1, text)
|
||||
self.assertNotEqual(result3, text)
|
||||
result1, result2 = result1.split(), result2.split()
|
||||
self.assertEqual(result1[:4], result2[:4])
|
||||
self.assertEqual(result1[1], "1")
|
||||
self.assertEqual(result1[2], "2")
|
||||
self.assertEqual(result2[-1], result2[-1])
|
||||
|
||||
def test_faulty_language(self):
|
||||
self.assertRaises(
|
||||
rplanguage.LanguageError,
|
||||
rplanguage.add_language,
|
||||
key='binary2',
|
||||
phonemes="w b d t oe ee, oo e o a wh dw bw", # erroneous comma
|
||||
grammar="cvvv cvv cvvcv cvvcvvo cvvvc cvvvcvv cvvc c v cc vv ccvvc ccvvccvv ",
|
||||
vowels="oea",
|
||||
word_length_variance=4)
|
||||
|
||||
|
||||
def test_available_languages(self):
|
||||
self.assertEqual(rplanguage.available_languages(), ["testlang"])
|
||||
self.assertEqual(rplanguage.available_languages(), ["testlang", "binary"])
|
||||
|
||||
def test_obfuscate_whisper(self):
|
||||
self.assertEqual(rplanguage.obfuscate_whisper(text, level=0.0), text)
|
||||
assert (rplanguage.obfuscate_whisper(text, level=0.1).startswith(
|
||||
'-utom-t-d t-sting is -dv-nt-g-ous for - numb-r of r--sons:t-sts m-y b- -x-cut-d Continuously'))
|
||||
'-utom-t-d t-sting is -dv-nt-g-ous for - numb-r of r--sons: t-sts m-y b- -x-cut-d Continuously'))
|
||||
assert(rplanguage.obfuscate_whisper(text, level=0.5).startswith(
|
||||
'--------- --s---- -s -----------s f-- - ------ -f ---s--s:--s-s '))
|
||||
'--------- --s---- -s -----------s f-- - ------ -f ---s--s: --s-s '))
|
||||
self.assertEqual(rplanguage.obfuscate_whisper(text, level=1.0), "...")
|
||||
|
||||
# Testing of emoting / sdesc / recog system
|
||||
|
|
|
|||
|
|
@ -1685,10 +1685,10 @@ class DefaultObject(with_metaclass(TypeclassBase, ObjectDB)):
|
|||
msg_type = 'whisper'
|
||||
msg_self = '{self} whisper to {all_receivers}, "{speech}"' if msg_self is True else msg_self
|
||||
msg_receivers = '{object} whispers: "{speech}"'
|
||||
msg_receivers = msg_receivers or '{object} whispers: "{speech}"'
|
||||
msg_location = None
|
||||
else:
|
||||
msg_self = '{self} say, "{speech}"' if msg_self is True else msg_self
|
||||
msg_receivers = None
|
||||
msg_location = msg_location or '{object} says, "{speech}"'
|
||||
|
||||
custom_mapping = kwargs.get('mapping', {})
|
||||
|
|
@ -1729,13 +1729,18 @@ class DefaultObject(with_metaclass(TypeclassBase, ObjectDB)):
|
|||
location_mapping = {"self": "You",
|
||||
"object": self,
|
||||
"location": location,
|
||||
"all_receivers": ", ".join(recv for recv in receivers) if receivers else None,
|
||||
"all_receivers": ", ".join(str(recv) for recv in receivers) if receivers else None,
|
||||
"receiver": None,
|
||||
"speech": message}
|
||||
location_mapping.update(custom_mapping)
|
||||
exclude = []
|
||||
if msg_self:
|
||||
exclude.append(self)
|
||||
if receivers:
|
||||
exclude.extend(receivers)
|
||||
self.location.msg_contents(text=(msg_location, {"type": msg_type}),
|
||||
from_obj=self,
|
||||
exclude=(self, ) if msg_self else None,
|
||||
exclude=exclude,
|
||||
mapping=location_mapping)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -13,8 +13,13 @@ try:
|
|||
except ImportError as error:
|
||||
errstr = """
|
||||
{err}
|
||||
SSL requires the PyOpenSSL library:
|
||||
pip install pyopenssl
|
||||
SSL requires the PyOpenSSL library and dependencies:
|
||||
|
||||
pip install pyopenssl pycrypto enum pyasn1 service_identity
|
||||
|
||||
Stop and start Evennia again. If no certificate can be generated, you'll
|
||||
get a suggestion for a (linux) command to generate this locally.
|
||||
|
||||
"""
|
||||
raise ImportError(errstr.format(err=error))
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ _RE_LINEBREAK = re.compile(r"\n\r|\r\n|\n|\r", re.DOTALL + re.MULTILINE)
|
|||
_RE_SCREENREADER_REGEX = re.compile(r"%s" % settings.SCREENREADER_REGEX_STRIP, re.DOTALL + re.MULTILINE)
|
||||
_IDLE_COMMAND = settings.IDLE_COMMAND + "\n"
|
||||
|
||||
|
||||
class TelnetProtocol(Telnet, StatefulTelnetProtocol, Session):
|
||||
"""
|
||||
Each player connecting over telnet (ie using most traditional mud
|
||||
|
|
@ -50,6 +49,8 @@ class TelnetProtocol(Telnet, StatefulTelnetProtocol, Session):
|
|||
# when it reaches 0 the portal/server syncs their data
|
||||
self.handshakes = 8 # suppress-go-ahead, naws, ttype, mccp, mssp, msdp, gmcp, mxp
|
||||
self.init_session(self.protocol_name, client_address, self.factory.sessionhandler)
|
||||
# change encoding to ENCODINGS[0] which reflects Telnet default encoding
|
||||
self.protocol_flags["ENCODING"] = settings.ENCODINGS[0] if settings.ENCODINGS else 'utf-8'
|
||||
|
||||
# suppress go-ahead
|
||||
self.sga = suppress_ga.SuppressGA(self)
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ from builtins import object
|
|||
|
||||
import time
|
||||
|
||||
|
||||
#------------------------------------------------------------
|
||||
# Server Session
|
||||
#------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -83,15 +83,20 @@ WEBCLIENT_ENABLED = True
|
|||
# default webclient will use this and only use the ajax version if the browser
|
||||
# is too old to support websockets. Requires WEBCLIENT_ENABLED.
|
||||
WEBSOCKET_CLIENT_ENABLED = True
|
||||
# Server-side websocket port to open for the webclient.
|
||||
# Server-side websocket port to open for the webclient. Note that this value will
|
||||
# be dynamically encoded in the webclient html page to allow the webclient to call
|
||||
# home. If the external encoded value needs to be different than this, due to
|
||||
# working through a proxy or docker port-remapping, the environment variable
|
||||
# WEBCLIENT_CLIENT_PROXY_PORT can be used to override this port only for the
|
||||
# front-facing client's sake.
|
||||
WEBSOCKET_CLIENT_PORT = 4005
|
||||
# Interface addresses to listen to. If 0.0.0.0, listen to all. Use :: for IPv6.
|
||||
WEBSOCKET_CLIENT_INTERFACE = '0.0.0.0'
|
||||
# Actual URL for webclient component to reach the websocket. You only need
|
||||
# to set this if you know you need it, like using some sort of proxy setup.
|
||||
# If given it must be on the form "ws://hostname" (WEBSOCKET_CLIENT_PORT will
|
||||
# be automatically appended). If left at None, the client will itself
|
||||
# figure out this url based on the server's hostname.
|
||||
# If given it must be on the form "ws[s]://hostname[:port]". If left at None,
|
||||
# the client will itself figure out this url based on the server's hostname.
|
||||
# e.g. ws://external.example.com or wss://external.example.com:443
|
||||
WEBSOCKET_CLIENT_URL = None
|
||||
# This determine's whether Evennia's custom admin page is used, or if the
|
||||
# standard Django admin is used.
|
||||
|
|
@ -166,6 +171,7 @@ IDLE_COMMAND = "idle"
|
|||
# given, this list is tried, in order, aborting on the first match.
|
||||
# Add sets for languages/regions your accounts are likely to use.
|
||||
# (see http://en.wikipedia.org/wiki/Character_encoding)
|
||||
# Telnet default encoding, unless specified by the client, will be ENCODINGS[0].
|
||||
ENCODINGS = ["utf-8", "latin-1", "ISO-8859-1"]
|
||||
# Regular expression applied to all output to a given session in order
|
||||
# to strip away characters (usually various forms of decorations) for the benefit
|
||||
|
|
@ -636,8 +642,6 @@ RSS_UPDATE_INTERVAL = 60 * 10 # 10 minutes
|
|||
# browser to display. Note however that this will leak memory when
|
||||
# active, so make sure to turn it off for a production server!
|
||||
DEBUG = False
|
||||
# While true, show "pretty" error messages for template syntax errors.
|
||||
TEMPLATE_DEBUG = DEBUG
|
||||
# Emails are sent to these people if the above DEBUG value is False. If you'd
|
||||
# rather prefer nobody receives emails, leave this commented out or empty.
|
||||
ADMINS = () # 'Your Name', 'your_email@domain.com'),)
|
||||
|
|
@ -730,7 +734,9 @@ TEMPLATES = [{
|
|||
'django.template.context_processors.media',
|
||||
'django.template.context_processors.debug',
|
||||
'sekizai.context_processors.sekizai',
|
||||
'evennia.web.utils.general_context.general_context']
|
||||
'evennia.web.utils.general_context.general_context'],
|
||||
# While true, show "pretty" error messages for template syntax errors.
|
||||
"debug": DEBUG
|
||||
}
|
||||
}]
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
# tuple.
|
||||
#
|
||||
|
||||
import os
|
||||
from django.conf import settings
|
||||
from evennia.utils.utils import get_evennia_version
|
||||
|
||||
|
|
@ -52,7 +53,11 @@ def set_webclient_settings():
|
|||
global WEBCLIENT_ENABLED, WEBSOCKET_CLIENT_ENABLED, WEBSOCKET_PORT, WEBSOCKET_URL
|
||||
WEBCLIENT_ENABLED = settings.WEBCLIENT_ENABLED
|
||||
WEBSOCKET_CLIENT_ENABLED = settings.WEBSOCKET_CLIENT_ENABLED
|
||||
WEBSOCKET_PORT = settings.WEBSOCKET_CLIENT_PORT
|
||||
# if we are working through a proxy or uses docker port-remapping, the webclient port encoded
|
||||
# in the webclient should be different than the one the server expects. Use the environment
|
||||
# variable WEBSOCKET_CLIENT_PROXY_PORT if this is the case.
|
||||
WEBSOCKET_PORT = int(os.environ.get("WEBSOCKET_CLIENT_PROXY_PORT", settings.WEBSOCKET_CLIENT_PORT))
|
||||
# this is determined dynamically by the client and is less of an issue
|
||||
WEBSOCKET_URL = settings.WEBSOCKET_CLIENT_URL
|
||||
set_webclient_settings()
|
||||
|
||||
|
|
|
|||
|
|
@ -51,9 +51,9 @@ class TestGeneralContext(TestCase):
|
|||
mock_settings.WEBCLIENT_ENABLED = "webclient"
|
||||
mock_settings.WEBSOCKET_CLIENT_URL = "websocket_url"
|
||||
mock_settings.WEBSOCKET_CLIENT_ENABLED = "websocket_client"
|
||||
mock_settings.WEBSOCKET_CLIENT_PORT = "websocket_port"
|
||||
mock_settings.WEBSOCKET_CLIENT_PORT = 5000
|
||||
general_context.set_webclient_settings()
|
||||
self.assertEqual(general_context.WEBCLIENT_ENABLED, "webclient")
|
||||
self.assertEqual(general_context.WEBSOCKET_URL, "websocket_url")
|
||||
self.assertEqual(general_context.WEBSOCKET_CLIENT_ENABLED, "websocket_client")
|
||||
self.assertEqual(general_context.WEBSOCKET_PORT, "websocket_port")
|
||||
self.assertEqual(general_context.WEBSOCKET_PORT, 5000)
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ JQuery available.
|
|||
{% endif %}
|
||||
|
||||
{% if websocket_url %}
|
||||
var wsurl = "{{websocket_url}}:{{websocket_port}}";
|
||||
var wsurl = "{{websocket_url}}";
|
||||
{% else %}
|
||||
var wsurl = "ws://" + this.location.hostname + ":{{websocket_port}}";
|
||||
{% endif %}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue