Merge branch 'evennia:main' into spawnupdate-fix
This commit is contained in:
commit
7c81d37e36
47 changed files with 422 additions and 373 deletions
27
.github/ISSUE_TEMPLATE/bug-report-develop.md
vendored
27
.github/ISSUE_TEMPLATE/bug-report-develop.md
vendored
|
|
@ -1,27 +0,0 @@
|
||||||
---
|
|
||||||
name: Bug report (branch-develop)
|
|
||||||
about: Use this to report errors in the Evennia `develop` branch
|
|
||||||
title: "[BUG - Develop] (Enter a brief description here)"
|
|
||||||
labels: bug, branch-develop, needs-triage
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
#### Describe the bug
|
|
||||||
<!--(This is for bugs in the develop-branch only. Make sure you test with the latest version.)-->
|
|
||||||
|
|
||||||
#### To Reproduce
|
|
||||||
Steps to reproduce the behavior:
|
|
||||||
1.
|
|
||||||
2.
|
|
||||||
3.
|
|
||||||
4. See error
|
|
||||||
|
|
||||||
#### Expected behavior
|
|
||||||
<!--(Replace with a clear and concise description of what you expected to happen.-->)
|
|
||||||
|
|
||||||
#### Develop-branch commit
|
|
||||||
<!--(The commit-hash. If unsure, run `evennia -v` or get the first few lines of the `about` command in-game.)-->
|
|
||||||
|
|
||||||
#### Additional context
|
|
||||||
<!--(Replace with any other context about the problem, or ideas on how to solve.)-->
|
|
||||||
|
|
@ -4,12 +4,12 @@ name: documentation
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ master, develop ]
|
branches: [ main, develop ]
|
||||||
paths:
|
paths:
|
||||||
- 'docs/**'
|
- 'docs/**'
|
||||||
- 'evennia/contrib/**'
|
- 'evennia/contrib/**'
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ master, develop ]
|
branches: [ main, develop ]
|
||||||
paths:
|
paths:
|
||||||
- 'docs/**'
|
- 'docs/**'
|
||||||
- 'evennia/contrib/**'
|
- 'evennia/contrib/**'
|
||||||
|
|
@ -48,8 +48,8 @@ jobs:
|
||||||
cd gamedir
|
cd gamedir
|
||||||
evennia migrate
|
evennia migrate
|
||||||
|
|
||||||
- name: Build and deploy docs (only from master/develop branch)
|
- name: Build and deploy docs (only from main/develop branch)
|
||||||
if: ${{ github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/master'}}
|
if: ${{ github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/main'}}
|
||||||
run: |
|
run: |
|
||||||
git config --global user.email "docbuilder@evennia.com"
|
git config --global user.email "docbuilder@evennia.com"
|
||||||
git config --global user.name "Evennia docbuilder action"
|
git config --global user.name "Evennia docbuilder action"
|
||||||
|
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
# This Evennia workflow will deploy the Evennia package automatically to
|
|
||||||
# pypi if vNN tag was given.
|
|
||||||
#
|
|
||||||
|
|
||||||
name: publish-evennia
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
tags: ['v*']
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-and-publish:
|
|
||||||
name: Build and publish Evennia to PyPi
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@master
|
|
||||||
|
|
||||||
- name: Set up Python 3.11
|
|
||||||
uses: actions/setup-python@v3
|
|
||||||
with:
|
|
||||||
python-version: "3.11"
|
|
||||||
|
|
||||||
- name: Install build
|
|
||||||
run: |
|
|
||||||
python -m pip install --upgrade pip
|
|
||||||
python -m pip install build --user
|
|
||||||
|
|
||||||
- name: Build binary wheel and source tarball
|
|
||||||
run: |
|
|
||||||
python -m build --sdist --wheel --outdir dist/ .
|
|
||||||
|
|
||||||
- name: Publish Evennia PyPi (on tag)
|
|
||||||
if: startsWith(github.ref, 'refs/tags')
|
|
||||||
uses: pypa/gh-action-pypi-publish@release/v1
|
|
||||||
with:
|
|
||||||
password: ${{ secrets.PYPI_API_TOKEN }}
|
|
||||||
30
.github/workflows/github_action_test_suite.yml
vendored
30
.github/workflows/github_action_test_suite.yml
vendored
|
|
@ -26,6 +26,12 @@ jobs:
|
||||||
TESTING_DB: "sqlite3"
|
TESTING_DB: "sqlite3"
|
||||||
coverage-test: true
|
coverage-test: true
|
||||||
|
|
||||||
|
timeout-minutes: 35
|
||||||
|
|
||||||
|
env:
|
||||||
|
UNIT_TEST_SETTINGS: "--settings=settings --keepdb --parallel 4 --timing"
|
||||||
|
COVERAGE_TEST_SETTINGS: "--settings=settings --timing"
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
|
@ -67,12 +73,7 @@ jobs:
|
||||||
if: ${{ ! matrix.coverage-test }}
|
if: ${{ ! matrix.coverage-test }}
|
||||||
working-directory: testing_mygame
|
working-directory: testing_mygame
|
||||||
run: |
|
run: |
|
||||||
evennia test \
|
evennia test ${{ env.UNIT_TEST_SETTINGS }} evennia
|
||||||
--settings=settings \
|
|
||||||
--keepdb \
|
|
||||||
--parallel 4 \
|
|
||||||
--timing \
|
|
||||||
evennia
|
|
||||||
|
|
||||||
# OBS - it's important to not run the coverage tests with --parallel, it messes up the coverage
|
# OBS - it's important to not run the coverage tests with --parallel, it messes up the coverage
|
||||||
# calculation!
|
# calculation!
|
||||||
|
|
@ -80,13 +81,8 @@ jobs:
|
||||||
if: ${{ matrix.coverage-test }}
|
if: ${{ matrix.coverage-test }}
|
||||||
working-directory: testing_mygame
|
working-directory: testing_mygame
|
||||||
run: |
|
run: |
|
||||||
coverage run \
|
coverage run --rcfile=../pyproject.toml ../bin/unix/evennia test ${{ env.COVERAGE_TEST_SETTINGS }} evennia
|
||||||
--source=evennia \
|
coverage combine
|
||||||
--omit=*/migrations/*,*/urls.py,*/test*.py,*.sh,*.txt,*.md,*.pyc,*.service \
|
|
||||||
../bin/unix/evennia test \
|
|
||||||
--settings=settings \
|
|
||||||
--timing \
|
|
||||||
evennia
|
|
||||||
coverage xml
|
coverage xml
|
||||||
coverage --version
|
coverage --version
|
||||||
coverage report | grep TOTAL
|
coverage report | grep TOTAL
|
||||||
|
|
@ -107,7 +103,7 @@ jobs:
|
||||||
name: Deploy Docker Image
|
name: Deploy Docker Image
|
||||||
needs: test
|
needs: test
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: ${{ github.repository == 'evennia/evennia' && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/develop') }}
|
if: ${{ github.repository == 'evennia/evennia' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/develop') }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
|
@ -123,9 +119,9 @@ jobs:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Build and push for master
|
- name: Build and push for main
|
||||||
if: ${{ github.ref == 'refs/heads/master' }}
|
if: ${{ github.ref == 'refs/heads/main' }}
|
||||||
id: docker_build_master
|
id: docker_build_main
|
||||||
uses: docker/build-push-action@v3
|
uses: docker/build-push-action@v3
|
||||||
with:
|
with:
|
||||||
push: true
|
push: true
|
||||||
|
|
|
||||||
45
.release.sh
Executable file
45
.release.sh
Executable file
|
|
@ -0,0 +1,45 @@
|
||||||
|
# Release helper
|
||||||
|
|
||||||
|
VERSION=$(cat evennia/VERSION.txt)
|
||||||
|
|
||||||
|
echo "This will release Evennia $VERSION (based on evennia/VERSION.txt)."
|
||||||
|
echo "Before continuing:"
|
||||||
|
echo " 1. Make sure you have Evennia upload credentials for Github (tagging) and PyPi (main package)."
|
||||||
|
echo " 2. Update CHANGELOG.md."
|
||||||
|
echo " 3. Run 'make local' in docs/ to update dynamic docs and autodocstrings (may have to run twice)."
|
||||||
|
echo " 4. Make sure VERSION.txt and pyproject.toml both show version $VERSION."
|
||||||
|
echo " 5. Make sure all changes are committed, e.g. as 'Evennia 1.x.x bug-fix release' (un-staged files will be wiped)."
|
||||||
|
echo " 6. Make sure all unit tests pass!"
|
||||||
|
|
||||||
|
read -p "Continue? [Y/n]> " yn
|
||||||
|
|
||||||
|
case $yn in
|
||||||
|
[nN] ) echo "Aborting.";
|
||||||
|
exit;;
|
||||||
|
* ) echo "Starting release ...";;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# clean and build the pypi distribution
|
||||||
|
echo "Preparing and Building PyPi package ..."
|
||||||
|
rm -Rf dist/
|
||||||
|
git clean -xdf
|
||||||
|
pip install --upgrade pip
|
||||||
|
pip install build twine
|
||||||
|
python -m build --sdist --wheel --outdir dist/ .
|
||||||
|
|
||||||
|
echo "Uploading PyPi package (requires PyPi credentials) ..."
|
||||||
|
|
||||||
|
python -m twine upload dist/*
|
||||||
|
|
||||||
|
# tag the latest git commit
|
||||||
|
echo "Creating and pushing release tag tag v$VERSION (requires GitHub credentials)..."
|
||||||
|
git tag -a v$VERSION -m "Evennia release v$VERSION"
|
||||||
|
git push --tags
|
||||||
|
|
||||||
|
echo "... Release complete."
|
||||||
|
echo ""
|
||||||
|
echo "Post-release actions:"
|
||||||
|
echo " 1. Make sure to push all commits."
|
||||||
|
echo " 2. Update github discussions to report on release."
|
||||||
|
echo " 2. Make post in discord #announcements channel pointing to discussion post."
|
||||||
|
echo " 3. Any other announcements as needed."
|
||||||
19
CHANGELOG.md
19
CHANGELOG.md
|
|
@ -1,11 +1,22 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
### Evennia 1.0
|
### Evennia 1.0.2
|
||||||
|
Dec 21, 2022
|
||||||
|
|
||||||
2019-2022 develop branch
|
Bug fix release. Fix more issues with discord bot reconnecting. Some doc
|
||||||
|
updates.
|
||||||
|
|
||||||
Changed to using `main` branch to follow github standard. Old `master` branch remains
|
### Evennia 1.0.1
|
||||||
for now but will not be used anymore, so as to not break installs during transition.
|
Dec 7, 2022
|
||||||
|
|
||||||
|
Bug fix release. Main issue was reconnect bug for discord bot.
|
||||||
|
|
||||||
|
## Evennia 1.0
|
||||||
|
|
||||||
|
2019-2022
|
||||||
|
|
||||||
|
_Changed to using `main` branch to follow github standard. Old `master` branch remains
|
||||||
|
for now but will not be used anymore, so as to not break installs during transition._
|
||||||
|
|
||||||
Increase requirements: Django 4.1+, Twisted 22.10+ Python 3.10, 3.11. PostgreSQL 11+.
|
Increase requirements: Django 4.1+, Twisted 22.10+ Python 3.10, 3.11. PostgreSQL 11+.
|
||||||
|
|
||||||
|
|
|
||||||
12
Makefile
12
Makefile
|
|
@ -13,7 +13,7 @@ default:
|
||||||
@echo " make test - run evennia test suite with all default values."
|
@echo " make test - run evennia test suite with all default values."
|
||||||
@echo " make tests=evennia.path test - run only specific test or tests."
|
@echo " make tests=evennia.path test - run only specific test or tests."
|
||||||
@echo " make testp - run test suite using multiple cores."
|
@echo " make testp - run test suite using multiple cores."
|
||||||
@echo " make publish - publish evennia to pypi (requires pypi credentials)
|
@echo " make release - publish evennia to pypi (requires pypi credentials)
|
||||||
|
|
||||||
install:
|
install:
|
||||||
pip install -e .
|
pip install -e .
|
||||||
|
|
@ -44,10 +44,8 @@ testp:
|
||||||
evennia migrate;\
|
evennia migrate;\
|
||||||
evennia test --keepdb --parallel 4 $(TESTS);\
|
evennia test --keepdb --parallel 4 $(TESTS);\
|
||||||
|
|
||||||
|
version:
|
||||||
|
echo $(VERSION)
|
||||||
|
|
||||||
release:
|
release:
|
||||||
rm -Rf dist/
|
./.release.sh
|
||||||
git clean -xdf
|
|
||||||
pip install --upgrade pip
|
|
||||||
pip install build twine
|
|
||||||
python -m build --sdist --wheel --outdir dist/ .
|
|
||||||
python -m twine upload dist/*
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# Evennia MUD/MU\* Creation System ![][logo]
|
# Evennia MUD/MU\* Creation System ![][logo]
|
||||||
[![Build Status][unittestciimg]][unittestcilink] [![Coverage Status][coverimg]][coverlink] [![Pypi Version][pypibadge]][pypilink]
|
[![unittestciimg]][unittestcilink] [![Coverage Status][coverimg]][coverlink] [![Pypi Version][pypibadge]][pypilink]
|
||||||
|
|
||||||
|
|
||||||
[Evennia][homepage] is a modern library for creating [online multiplayer text
|
[Evennia][homepage] is a modern library for creating [online multiplayer text
|
||||||
|
|
@ -48,8 +48,8 @@ Welcome!
|
||||||
[logo]: https://github.com/evennia/evennia/blob/master/evennia/web/website/static/website/images/evennia_logo.png
|
[logo]: https://github.com/evennia/evennia/blob/master/evennia/web/website/static/website/images/evennia_logo.png
|
||||||
[unittestciimg]: https://github.com/evennia/evennia/workflows/test-suite/badge.svg
|
[unittestciimg]: https://github.com/evennia/evennia/workflows/test-suite/badge.svg
|
||||||
[unittestcilink]: https://github.com/evennia/evennia/actions?query=workflow%3Atest-suite
|
[unittestcilink]: https://github.com/evennia/evennia/actions?query=workflow%3Atest-suite
|
||||||
[coverimg]: https://coveralls.io/repos/github/evennia/evennia/badge.svg?branch=master
|
[coverimg]: https://coveralls.io/repos/github/evennia/evennia/badge.svg?branch=main
|
||||||
[coverlink]: https://coveralls.io/github/evennia/evennia?branch=master
|
[coverlink]: https://coveralls.io/github/evennia/evennia?branch=main
|
||||||
[pypibadge]: https://img.shields.io/pypi/v/evennia?color=blue
|
[pypibadge]: https://img.shields.io/pypi/v/evennia?color=blue
|
||||||
[pypilink]: https://pypi.org/project/evennia/
|
[pypilink]: https://pypi.org/project/evennia/
|
||||||
[introduction]: https://www.evennia.com/docs/latest/Evennia-Introduction.html
|
[introduction]: https://www.evennia.com/docs/latest/Evennia-Introduction.html
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,22 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
### Evennia 1.0
|
### Evennia 1.0.2
|
||||||
|
Dec 21, 2022
|
||||||
|
|
||||||
2019-2022 develop branch
|
Bug fix release. Fix more issues with discord bot reconnecting. Some doc
|
||||||
|
updates.
|
||||||
|
|
||||||
Changed to using `main` branch to follow github standard. Old `master` branch remains
|
### Evennia 1.0.1
|
||||||
for now but will not be used anymore, so as to not break installs during transition.
|
Dec 7, 2022
|
||||||
|
|
||||||
|
Bug fix release. Main issue was reconnect bug for discord bot.
|
||||||
|
|
||||||
|
## Evennia 1.0
|
||||||
|
|
||||||
|
2019-2022
|
||||||
|
|
||||||
|
_Changed to using `main` branch to follow github standard. Old `master` branch remains
|
||||||
|
for now but will not be used anymore, so as to not break installs during transition._
|
||||||
|
|
||||||
Increase requirements: Django 4.1+, Twisted 22.10+ Python 3.10, 3.11. PostgreSQL 11+.
|
Increase requirements: Django 4.1+, Twisted 22.10+ Python 3.10, 3.11. PostgreSQL 11+.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
This summarizes the changes. See the [Changelog](./Changelog.md) for the full list.
|
This summarizes the changes. See the [Changelog](./Changelog.md) for the full list.
|
||||||
|
|
||||||
|
- Main development now on `main` branch. `master` branch remains, but will not be updated anymore.
|
||||||
|
|
||||||
## Minimum requirements
|
## Minimum requirements
|
||||||
|
|
||||||
- Python 3.10 is now required minimum. Ubuntu LTS now installs with 3.10. Evennia 1.0 is also tested with Python 3.11 - this is the recommended version for Linux/Mac. Windows users may want to stay on Python 3.10 unless they are okay with installing a C++ compiler.
|
- Python 3.10 is now required minimum. Ubuntu LTS now installs with 3.10. Evennia 1.0 is also tested with Python 3.11 - this is the recommended version for Linux/Mac. Windows users may want to stay on Python 3.10 unless they are okay with installing a C++ compiler.
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ forces Evennia to use this settings file over the default one.
|
||||||
|
|
||||||
You can also test specific things by giving their path
|
You can also test specific things by giving their path
|
||||||
|
|
||||||
evennia test --settings settings.py .world.tests.YourTest
|
evennia test --settings settings.py world.tests.YourTest
|
||||||
|
|
||||||
|
|
||||||
## Writing new unit tests
|
## Writing new unit tests
|
||||||
|
|
@ -106,15 +106,15 @@ To test this, run
|
||||||
|
|
||||||
to run the entire test module
|
to run the entire test module
|
||||||
|
|
||||||
evennia test --settings setings.py .world.tests
|
evennia test --settings setings.py world.tests
|
||||||
|
|
||||||
or a specific class:
|
or a specific class:
|
||||||
|
|
||||||
evennia test --settings settings.py .world.tests.TestObj
|
evennia test --settings settings.py world.tests.TestObj
|
||||||
|
|
||||||
You can also run a specific test:
|
You can also run a specific test:
|
||||||
|
|
||||||
evennia test --settings settings.py .world.tests.TestObj.test_alternative_call
|
evennia test --settings settings.py world.tests.TestObj.test_alternative_call
|
||||||
|
|
||||||
You might also want to read the [Python documentation for the unittest module](https://docs.python.org/library/unittest.html).
|
You might also want to read the [Python documentation for the unittest module](https://docs.python.org/library/unittest.html).
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -295,7 +295,7 @@ You can't do `git push upstream` unless you have write-access to the upstream Ev
|
||||||
This should be done in your fork of Evennia. You should _always_ do this in a _separate git branch_ based off the Evennia branch you want to improve.
|
This should be done in your fork of Evennia. You should _always_ do this in a _separate git branch_ based off the Evennia branch you want to improve.
|
||||||
|
|
||||||
git checkout main (or develop)
|
git checkout main (or develop)
|
||||||
git branch - b myfixbranch
|
git branch -b myfixbranch
|
||||||
|
|
||||||
Now fix whatever needs fixing. Abide by the [Evennia code style](./Evennia-Code-Style.md). You can `git commit` commit your changes along the way as normal.
|
Now fix whatever needs fixing. Abide by the [Evennia code style](./Evennia-Code-Style.md). You can `git commit` commit your changes along the way as normal.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ updated after Sept 2022 will be missing some translations.
|
||||||
+---------------+----------------------+--------------+
|
+---------------+----------------------+--------------+
|
||||||
| es | Spanish | Aug 2019 |
|
| es | Spanish | Aug 2019 |
|
||||||
+---------------+----------------------+--------------+
|
+---------------+----------------------+--------------+
|
||||||
| fr | French | Mar 2022 |
|
| fr | French | Dec 2022 |
|
||||||
+---------------+----------------------+--------------+
|
+---------------+----------------------+--------------+
|
||||||
| it | Italian | Oct 2022 |
|
| it | Italian | Oct 2022 |
|
||||||
+---------------+----------------------+--------------+
|
+---------------+----------------------+--------------+
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ is being combined instead):
|
||||||
See the [sword example](evennia.contrib.game_systems.crafting.example_recipes) for an example
|
See the [sword example](evennia.contrib.game_systems.crafting.example_recipes) for an example
|
||||||
of how to design a recipe tree for crafting a sword from base elements.
|
of how to design a recipe tree for crafting a sword from base elements.
|
||||||
|
|
||||||
## Intallation and Usage
|
## Installation and Usage
|
||||||
|
|
||||||
Import the `CmdCraft` command from evennia/contrib/crafting/crafting.py and
|
Import the `CmdCraft` command from evennia/contrib/crafting/crafting.py and
|
||||||
add it to your Character cmdset. Reload and the `craft` command will be
|
add it to your Character cmdset. Reload and the `craft` command will be
|
||||||
|
|
|
||||||
|
|
@ -16,11 +16,12 @@ In more detail, in `mygame/commands/default_cmdsets.py`:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
...
|
...
|
||||||
from evennia.contrib import extended_room # <---
|
from evennia.contrib.grid import extended_room # <---
|
||||||
|
|
||||||
class CharacterCmdset(default_cmds.Character_CmdSet):
|
class CharacterCmdset(default_cmds.CharacterCmdSet):
|
||||||
...
|
...
|
||||||
def at_cmdset_creation(self):
|
def at_cmdset_creation(self):
|
||||||
|
super().at_cmdset_creation()
|
||||||
...
|
...
|
||||||
self.add(extended_room.ExtendedRoomCmdSet) # <---
|
self.add(extended_room.ExtendedRoomCmdSet) # <---
|
||||||
|
|
||||||
|
|
@ -28,7 +29,10 @@ class CharacterCmdset(default_cmds.Character_CmdSet):
|
||||||
|
|
||||||
Then reload to make the new commands available. Note that they only work
|
Then reload to make the new commands available. Note that they only work
|
||||||
on rooms with the typeclass `ExtendedRoom`. Create new rooms with the right
|
on rooms with the typeclass `ExtendedRoom`. Create new rooms with the right
|
||||||
typeclass or use the `typeclass` command to swap existing rooms.
|
typeclass or use the `typeclass` command to swap existing rooms. Note that since
|
||||||
|
this contrib overrides the `look` command, you will need to add the
|
||||||
|
`extended_room.ExtendedRoomCmdSet` to the default character cmdset *after*
|
||||||
|
super().at_cmdset_creation(), or it will be overridden by the default look.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,7 @@ Start small. Evennia's [Beginner tutorial](Howtos/Beginner-Tutorial/Beginner-Tut
|
||||||
```{sidebar}
|
```{sidebar}
|
||||||
See also our [link page](./Links.md) for some reading suggestions.
|
See also our [link page](./Links.md) for some reading suggestions.
|
||||||
```
|
```
|
||||||
|
|
||||||
While Python is considered a very easy programming language to get into, you do have a learning curve to climb if you are new to programming. The beginner-tutorial has a [basic introduction to Python](Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Python-basic-introduction.md), but if you are completely new, you should probably also sit down with a full Python beginner's tutorial at some point. There are plenty of them on the web if you look around.
|
While Python is considered a very easy programming language to get into, you do have a learning curve to climb if you are new to programming. The beginner-tutorial has a [basic introduction to Python](Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Python-basic-introduction.md), but if you are completely new, you should probably also sit down with a full Python beginner's tutorial at some point. There are plenty of them on the web if you look around.
|
||||||
|
|
||||||
To code your dream game in Evennia you don't need to be a Python guru, but you do need to be able to read example code containing at least these basic Python features:
|
To code your dream game in Evennia you don't need to be a Python guru, but you do need to be able to read example code containing at least these basic Python features:
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,7 @@ class LivingMixin:
|
||||||
healed = min(damage, hp)
|
healed = min(damage, hp)
|
||||||
self.hp += healed
|
self.hp += healed
|
||||||
|
|
||||||
self.msg("You heal for {healed} HP.")
|
self.msg(f"You heal for {healed} HP.")
|
||||||
|
|
||||||
def at_pay(self, amount):
|
def at_pay(self, amount):
|
||||||
"""When paying coins, make sure to never detract more than we have"""
|
"""When paying coins, make sure to never detract more than we have"""
|
||||||
|
|
|
||||||
|
|
@ -92,6 +92,7 @@ If `localhost` doesn't work when trying to connect to your local game, try `127.
|
||||||
instead. Some MUD clients on Windows does not appear to understand the alias `localhost`.
|
instead. Some MUD clients on Windows does not appear to understand the alias `localhost`.
|
||||||
- Some Windows users get an error installing the Twisted 'wheel'. A wheel is a pre-compiled binary
|
- Some Windows users get an error installing the Twisted 'wheel'. A wheel is a pre-compiled binary
|
||||||
package for Python. A common reason for this error is that you are using a 32-bit version of Python, but Twisted has not yet uploaded the latest 32-bit wheel. Easiest way to fix this is to install a slightly older Twisted version. So if, say, version `22.1` failed, install `22.0` manually with `pip install twisted==22.0`. Alternatively you could check that you are using the 64-bit version of Python and uninstall any 32bit one. If so, you must then `deactivate` the virtualenv, delete the `evenv` folder and recreate it anew with your new Python.
|
package for Python. A common reason for this error is that you are using a 32-bit version of Python, but Twisted has not yet uploaded the latest 32-bit wheel. Easiest way to fix this is to install a slightly older Twisted version. So if, say, version `22.1` failed, install `22.0` manually with `pip install twisted==22.0`. Alternatively you could check that you are using the 64-bit version of Python and uninstall any 32bit one. If so, you must then `deactivate` the virtualenv, delete the `evenv` folder and recreate it anew with your new Python.
|
||||||
|
- If you've done a git installation, and your server won't start with an error message like `AttributeError: module 'evennia' has no attribute '_init'`, it may be a python path issue. In a terminal, cd to `(your python directory)\site-packages` and run the command `echo "C:\absolute\path\to\evennia" > local-vendors.pth`. Open the created file in your favorite IDE and make sure it is saved with *UTF-8* encoding and not *UTF-8 with BOM*.
|
||||||
- If your server won't start, with no error messages (and no log files at all when starting from
|
- If your server won't start, with no error messages (and no log files at all when starting from
|
||||||
scratch), try to start with `evennia ipstart` instead. If you then see an error about `system cannot find the path specified`, it may be that the file `evennia\evennia\server\twistd.bat` has the wrong path to the `twistd` executable. This file is auto-generated, so try to delete it and then run `evennia start` to rebuild it and see if it works. If it still doesn't work you need to open it in a text editor like Notepad. It's just one line containing the path to the `twistd.exe` executable as determined by Evennia. If you installed Twisted in a non-standard location this might be wrong and you should update the line to the real location.
|
scratch), try to start with `evennia ipstart` instead. If you then see an error about `system cannot find the path specified`, it may be that the file `evennia\evennia\server\twistd.bat` has the wrong path to the `twistd` executable. This file is auto-generated, so try to delete it and then run `evennia start` to rebuild it and see if it works. If it still doesn't work you need to open it in a text editor like Notepad. It's just one line containing the path to the `twistd.exe` executable as determined by Evennia. If you installed Twisted in a non-standard location this might be wrong and you should update the line to the real location.
|
||||||
- Some users have reported issues with Windows WSL and anti-virus software during Evennia
|
- Some users have reported issues with Windows WSL and anti-virus software during Evennia
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,8 @@ Prior to 1.0, all Evennia installs were [Git-installs](./Installation-Git.md). T
|
||||||
- Make a _new_ `evenv` virtualenv (see the [virtualenv instructions](./Installation-Git.md#virtualenv) for help) and make sure it's active
|
- Make a _new_ `evenv` virtualenv (see the [virtualenv instructions](./Installation-Git.md#virtualenv) for help) and make sure it's active
|
||||||
- `cd` into your `evennia/` root folder (you want to be where you see the `docs/` and `bin/` directories as well as a nested `evennia/` folder)
|
- `cd` into your `evennia/` root folder (you want to be where you see the `docs/` and `bin/` directories as well as a nested `evennia/` folder)
|
||||||
- `git pull`
|
- `git pull`
|
||||||
- `git checkout main` (the `master`)
|
- `git checkout main` (instead of `master` which was used for `0.9.5`)
|
||||||
- `pip install -e --upgrade .`
|
- `pip install --upgrade -e .`
|
||||||
- If you want the optional extra libs (needed by some contribs), do `pip install -e --upgrade .[extra]`
|
- If you want the optional extra libs (needed by some contribs), do `pip install -e --upgrade .[extra]`
|
||||||
- Test that you can run the `evennia` command.
|
- Test that you can run the `evennia` command.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -328,7 +328,7 @@ Evennia users:
|
||||||
| [Amazon Lightsail][9] | Cloud | $5/month | Free first month. AWS's "fixed cost" offering.|
|
| [Amazon Lightsail][9] | Cloud | $5/month | Free first month. AWS's "fixed cost" offering.|
|
||||||
| [Azure App Services][12] | Cloud | Free | Free tier with limited regions for hobbyists. |
|
| [Azure App Services][12] | Cloud | Free | Free tier with limited regions for hobbyists. |
|
||||||
| [Huawei Cloud][13] | Cloud | on demand | Similar to Amazon. Free 12-month tier with limited regions. |
|
| [Huawei Cloud][13] | Cloud | on demand | Similar to Amazon. Free 12-month tier with limited regions. |
|
||||||
| [Host1Plus][5] | VPS & Cloud | $4/month | $4-$8/month depending on length of sign-up period.
|
| [Heficed][5] | VPS & Cloud | $6/month | $6/month for a 1GB ram server. |
|
||||||
| [Scaleway][6] | Cloud | €3/month / on-demand | EU based (Paris, Amsterdam). Smallest option provides 2GB RAM. |
|
| [Scaleway][6] | Cloud | €3/month / on-demand | EU based (Paris, Amsterdam). Smallest option provides 2GB RAM. |
|
||||||
| [Prgmr][10] | VPS | $5/month | 1 month free with a year prepay. You likely want some experience with servers with this option as they don't have a lot of support.|
|
| [Prgmr][10] | VPS | $5/month | 1 month free with a year prepay. You likely want some experience with servers with this option as they don't have a lot of support.|
|
||||||
| [Linode][11] | Cloud | $5/month / on-demand | Multiple regions. Smallest option provides 1GB RAM|
|
| [Linode][11] | Cloud | $5/month / on-demand | Multiple regions. Smallest option provides 1GB RAM|
|
||||||
|
|
@ -340,7 +340,7 @@ Evennia users:
|
||||||
[2]: https://www.digitalocean.com/pricing
|
[2]: https://www.digitalocean.com/pricing
|
||||||
[3]: https://aws.amazon.com/pricing/
|
[3]: https://aws.amazon.com/pricing/
|
||||||
[4]: https://www.genesismuds.com/
|
[4]: https://www.genesismuds.com/
|
||||||
[5]: https://www.host1plus.com/
|
[5]: https://www.heficed.com/
|
||||||
[6]: https://www.scaleway.com/
|
[6]: https://www.scaleway.com/
|
||||||
[7]: https://lowendbox.com/
|
[7]: https://lowendbox.com/
|
||||||
[8]: https://www.lowendtalk.com
|
[8]: https://www.lowendtalk.com
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
1.0-dev
|
1.0.2
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,6 @@ import time
|
||||||
from codecs import lookup as codecs_lookup
|
from codecs import lookup as codecs_lookup
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
from evennia.server.sessionhandler import SESSIONS
|
from evennia.server.sessionhandler import SESSIONS
|
||||||
from evennia.utils import create, logger, search, utils
|
from evennia.utils import create, logger, search, utils
|
||||||
|
|
||||||
|
|
@ -191,7 +190,8 @@ class CmdCharCreate(COMMAND_DEFAULT_CLASS):
|
||||||
elif not new_character.db.desc:
|
elif not new_character.db.desc:
|
||||||
new_character.db.desc = "This is a character."
|
new_character.db.desc = "This is a character."
|
||||||
self.msg(
|
self.msg(
|
||||||
f"Created new character {new_character.key}. Use |wic {new_character.key}|n to enter the game as this character."
|
f"Created new character {new_character.key}. Use |wic {new_character.key}|n to enter"
|
||||||
|
" the game as this character."
|
||||||
)
|
)
|
||||||
logger.log_sec(
|
logger.log_sec(
|
||||||
f"Character Created: {new_character} (Caller: {account}, IP: {self.session.address})."
|
f"Character Created: {new_character} (Caller: {account}, IP: {self.session.address})."
|
||||||
|
|
@ -317,11 +317,13 @@ class CmdIC(COMMAND_DEFAULT_CLASS):
|
||||||
if account.db._playable_characters:
|
if account.db._playable_characters:
|
||||||
# look at the playable_characters list first
|
# look at the playable_characters list first
|
||||||
character_candidates.extend(
|
character_candidates.extend(
|
||||||
account.search(
|
utils.make_iter(
|
||||||
self.args,
|
account.search(
|
||||||
candidates=account.db._playable_characters,
|
self.args,
|
||||||
search_object=True,
|
candidates=account.db._playable_characters,
|
||||||
quiet=True,
|
search_object=True,
|
||||||
|
quiet=True,
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -370,12 +372,14 @@ class CmdIC(COMMAND_DEFAULT_CLASS):
|
||||||
account.puppet_object(session, new_character)
|
account.puppet_object(session, new_character)
|
||||||
account.db._last_puppet = new_character
|
account.db._last_puppet = new_character
|
||||||
logger.log_sec(
|
logger.log_sec(
|
||||||
f"Puppet Success: (Caller: {account}, Target: {new_character}, IP: {self.session.address})."
|
f"Puppet Success: (Caller: {account}, Target: {new_character}, IP:"
|
||||||
|
f" {self.session.address})."
|
||||||
)
|
)
|
||||||
except RuntimeError as exc:
|
except RuntimeError as exc:
|
||||||
self.msg(f"|rYou cannot become |C{new_character.name}|n: {exc}")
|
self.msg(f"|rYou cannot become |C{new_character.name}|n: {exc}")
|
||||||
logger.log_sec(
|
logger.log_sec(
|
||||||
f"Puppet Failed: %s (Caller: {account}, Target: {new_character}, IP: {self.session.address})."
|
f"Puppet Failed: %s (Caller: {account}, Target: {new_character}, IP:"
|
||||||
|
f" {self.session.address})."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -670,7 +674,8 @@ class CmdOption(COMMAND_DEFAULT_CLASS):
|
||||||
else:
|
else:
|
||||||
flags[new_name] = new_val
|
flags[new_name] = new_val
|
||||||
self.msg(
|
self.msg(
|
||||||
f"Option |w{new_name}|n was changed from '|w{old_val}|n' to '|w{new_val}|n'."
|
f"Option |w{new_name}|n was changed from '|w{old_val}|n' to"
|
||||||
|
f" '|w{new_val}|n'."
|
||||||
)
|
)
|
||||||
return {new_name: new_val}
|
return {new_name: new_val}
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
|
|
@ -1024,7 +1029,7 @@ class CmdStyle(COMMAND_DEFAULT_CLASS):
|
||||||
style <option> = <value>
|
style <option> = <value>
|
||||||
|
|
||||||
Configure stylings for in-game display elements like table borders, help
|
Configure stylings for in-game display elements like table borders, help
|
||||||
entriest etc. Use without arguments to see all available options.
|
entries etc. Use without arguments to see all available options.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1925,6 +1925,7 @@ class CmdDiscord2Chan(COMMAND_DEFAULT_CLASS):
|
||||||
/delete - alias to remove
|
/delete - alias to remove
|
||||||
/guild - toggle the Discord server tag on/off
|
/guild - toggle the Discord server tag on/off
|
||||||
/channel - toggle the Evennia/Discord channel tags on/off
|
/channel - toggle the Evennia/Discord channel tags on/off
|
||||||
|
/start - tell the bot to start, in case it lost its connection
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
discord2chan mydiscord = 555555555555555
|
discord2chan mydiscord = 555555555555555
|
||||||
|
|
@ -1943,6 +1944,7 @@ class CmdDiscord2Chan(COMMAND_DEFAULT_CLASS):
|
||||||
"guild",
|
"guild",
|
||||||
"list",
|
"list",
|
||||||
"remove",
|
"remove",
|
||||||
|
"start",
|
||||||
)
|
)
|
||||||
locks = "cmd:serversetting(DISCORD_ENABLED) and pperm(Developer)"
|
locks = "cmd:serversetting(DISCORD_ENABLED) and pperm(Developer)"
|
||||||
help_category = "Comms"
|
help_category = "Comms"
|
||||||
|
|
@ -1973,6 +1975,13 @@ class CmdDiscord2Chan(COMMAND_DEFAULT_CLASS):
|
||||||
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 not match {settings.DISCORD_BOT_CLASS} in settings!"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if "start" in self.switches:
|
||||||
|
if discord_bot.sessions.all():
|
||||||
|
self.msg("The Discord bot is already running.")
|
||||||
|
else:
|
||||||
|
discord_bot.start()
|
||||||
|
return
|
||||||
|
|
||||||
if "guild" in self.switches:
|
if "guild" in self.switches:
|
||||||
discord_bot.db.tag_guild = not discord_bot.db.tag_guild
|
discord_bot.db.tag_guild = not discord_bot.db.tag_guild
|
||||||
self.msg(
|
self.msg(
|
||||||
|
|
|
||||||
|
|
@ -371,8 +371,9 @@ class CmdInventory(COMMAND_DEFAULT_CLASS):
|
||||||
|
|
||||||
table = self.styled_table(border="header")
|
table = self.styled_table(border="header")
|
||||||
for item in items:
|
for item in items:
|
||||||
|
singular, _ = item.get_numbered_name(1, self.caller)
|
||||||
table.add_row(
|
table.add_row(
|
||||||
f"|C{item.name}|n",
|
f"|C{singular}|n",
|
||||||
"{}|n".format(utils.crop(raw_ansi(item.db.desc or ""), width=50) or ""),
|
"{}|n".format(utils.crop(raw_ansi(item.db.desc or ""), width=50) or ""),
|
||||||
)
|
)
|
||||||
string = f"|wYou are carrying:\n{table}"
|
string = f"|wYou are carrying:\n{table}"
|
||||||
|
|
@ -424,8 +425,8 @@ class CmdGet(COMMAND_DEFAULT_CLASS):
|
||||||
if not success:
|
if not success:
|
||||||
caller.msg("This can't be picked up.")
|
caller.msg("This can't be picked up.")
|
||||||
else:
|
else:
|
||||||
caller.msg(f"You pick up {obj.name}.")
|
singular, _ = obj.get_numbered_name(1, caller)
|
||||||
caller.location.msg_contents(f"{caller.name} picks up {obj.name}.", exclude=caller)
|
caller.location.msg_contents(f"$You() $conj(pick) up {singular}.", from_obj=caller)
|
||||||
# calling at_get hook method
|
# calling at_get hook method
|
||||||
obj.at_get(caller)
|
obj.at_get(caller)
|
||||||
|
|
||||||
|
|
@ -472,8 +473,8 @@ class CmdDrop(COMMAND_DEFAULT_CLASS):
|
||||||
if not success:
|
if not success:
|
||||||
caller.msg("This couldn't be dropped.")
|
caller.msg("This couldn't be dropped.")
|
||||||
else:
|
else:
|
||||||
caller.msg("You drop %s." % (obj.name,))
|
singular, _ = obj.get_numbered_name(1, caller)
|
||||||
caller.location.msg_contents(f"{caller.name} drops {obj.name}.", exclude=caller)
|
caller.location.msg_contents(f"$You() $conj(drop) {singular}.", from_obj=caller)
|
||||||
# Call the object script's at_drop() method.
|
# Call the object script's at_drop() method.
|
||||||
obj.at_drop(caller)
|
obj.at_drop(caller)
|
||||||
|
|
||||||
|
|
@ -510,11 +511,13 @@ class CmdGive(COMMAND_DEFAULT_CLASS):
|
||||||
target = caller.search(self.rhs)
|
target = caller.search(self.rhs)
|
||||||
if not (to_give and target):
|
if not (to_give and target):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
singular, _ = to_give.get_numbered_name(1, caller)
|
||||||
if target == caller:
|
if target == caller:
|
||||||
caller.msg(f"You keep {to_give.key} to yourself.")
|
caller.msg(f"You keep {singular} to yourself.")
|
||||||
return
|
return
|
||||||
if not to_give.location == caller:
|
if not to_give.location == caller:
|
||||||
caller.msg(f"You are not holding {to_give.key}.")
|
caller.msg(f"You are not holding {singular}.")
|
||||||
return
|
return
|
||||||
|
|
||||||
# calling at_pre_give hook method
|
# calling at_pre_give hook method
|
||||||
|
|
@ -524,10 +527,10 @@ class CmdGive(COMMAND_DEFAULT_CLASS):
|
||||||
# give object
|
# give object
|
||||||
success = to_give.move_to(target, quiet=True, move_type="give")
|
success = to_give.move_to(target, quiet=True, move_type="give")
|
||||||
if not success:
|
if not success:
|
||||||
caller.msg(f"You could not give {to_give.key}.")
|
caller.msg(f"You could not give {singular} to {target.key}.")
|
||||||
else:
|
else:
|
||||||
caller.msg(f"You give {to_give.key} to {target.key}.")
|
caller.msg(f"You give {singular} to {target.key}.")
|
||||||
target.msg(f"{caller.key} gives you {to_give.key}.")
|
target.msg(f"{caller.key} gives you {singular}.")
|
||||||
# Call the object script's at_give() method.
|
# Call the object script's at_give() method.
|
||||||
to_give.at_give(caller, target)
|
to_give.at_give(caller, target)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -627,7 +627,7 @@ class CmdHelp(COMMAND_DEFAULT_CLASS):
|
||||||
)
|
)
|
||||||
if suggestions:
|
if suggestions:
|
||||||
help_text += (
|
help_text += (
|
||||||
"\n... But matches where found within the help "
|
"\n... But matches were found within the help "
|
||||||
"texts of the suggestions below."
|
"texts of the suggestions below."
|
||||||
)
|
)
|
||||||
suggestions = [
|
suggestions = [
|
||||||
|
|
|
||||||
|
|
@ -112,13 +112,13 @@ class TestGeneral(BaseEvenniaCommandTest):
|
||||||
self.call(general.CmdNick(), "/list", "Defined Nicks:")
|
self.call(general.CmdNick(), "/list", "Defined Nicks:")
|
||||||
|
|
||||||
def test_get_and_drop(self):
|
def test_get_and_drop(self):
|
||||||
self.call(general.CmdGet(), "Obj", "You pick up Obj.")
|
self.call(general.CmdGet(), "Obj", "You pick up an Obj.")
|
||||||
self.call(general.CmdDrop(), "Obj", "You drop Obj.")
|
self.call(general.CmdDrop(), "Obj", "You drop an Obj.")
|
||||||
|
|
||||||
def test_give(self):
|
def test_give(self):
|
||||||
self.call(general.CmdGive(), "Obj to Char2", "You aren't carrying Obj.")
|
self.call(general.CmdGive(), "Obj to Char2", "You aren't carrying Obj.")
|
||||||
self.call(general.CmdGive(), "Obj = Char2", "You aren't carrying Obj.")
|
self.call(general.CmdGive(), "Obj = Char2", "You aren't carrying Obj.")
|
||||||
self.call(general.CmdGet(), "Obj", "You pick up Obj.")
|
self.call(general.CmdGet(), "Obj", "You pick up an Obj.")
|
||||||
self.call(general.CmdGive(), "Obj to Char2", "You give")
|
self.call(general.CmdGive(), "Obj to Char2", "You give")
|
||||||
self.call(general.CmdGive(), "Obj = Char", "You give", caller=self.char2)
|
self.call(general.CmdGive(), "Obj = Char", "You give", caller=self.char2)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ class Character(ComponentHolderMixin, DefaultCharacter):
|
||||||
|
|
||||||
Components need to inherit the Component class directly and require a name.
|
Components need to inherit the Component class directly and require a name.
|
||||||
```python
|
```python
|
||||||
from evennia.contrib.components import Component
|
from evennia.contrib.base_systems.components import Component
|
||||||
|
|
||||||
class Health(Component):
|
class Health(Component):
|
||||||
name = "health"
|
name = "health"
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ is being combined instead):
|
||||||
See the [sword example](evennia.contrib.game_systems.crafting.example_recipes) for an example
|
See the [sword example](evennia.contrib.game_systems.crafting.example_recipes) for an example
|
||||||
of how to design a recipe tree for crafting a sword from base elements.
|
of how to design a recipe tree for crafting a sword from base elements.
|
||||||
|
|
||||||
## Intallation and Usage
|
## Installation and Usage
|
||||||
|
|
||||||
Import the `CmdCraft` command from evennia/contrib/crafting/crafting.py and
|
Import the `CmdCraft` command from evennia/contrib/crafting/crafting.py and
|
||||||
add it to your Character cmdset. Reload and the `craft` command will be
|
add it to your Character cmdset. Reload and the `craft` command will be
|
||||||
|
|
@ -115,7 +115,7 @@ class RecipeBread(CraftingRecipe):
|
||||||
## Adding new recipes
|
## Adding new recipes
|
||||||
|
|
||||||
A *recipe* is a class inheriting from
|
A *recipe* is a class inheriting from
|
||||||
`evennia.contrib.crafting.crafting.CraftingRecipe`. This class implements the
|
`evennia.contrib.game_systems.crafting.CraftingRecipe`. This class implements the
|
||||||
most common form of crafting - that using in-game objects. Each recipe is a
|
most common form of crafting - that using in-game objects. Each recipe is a
|
||||||
separate class which gets initialized with the consumables/tools you provide.
|
separate class which gets initialized with the consumables/tools you provide.
|
||||||
|
|
||||||
|
|
@ -137,7 +137,7 @@ example setting:
|
||||||
```python
|
```python
|
||||||
# in mygame/world/myrecipes.py
|
# in mygame/world/myrecipes.py
|
||||||
|
|
||||||
from evennia.contrib.crafting.crafting import CraftingRecipe
|
from evennia.contrib.game_systems.crafting import CraftingRecipe
|
||||||
|
|
||||||
class WoodenPuppetRecipe(CraftingRecipe):
|
class WoodenPuppetRecipe(CraftingRecipe):
|
||||||
"""A puppet""""
|
"""A puppet""""
|
||||||
|
|
@ -200,7 +200,7 @@ in-game command:
|
||||||
In code we would do
|
In code we would do
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from evennia.contrib.crafting.crafting import craft
|
from evennia.contrib.game_systems.crafting import craft
|
||||||
puppet = craft(crafter, "wooden puppet", knife, wood)
|
puppet = craft(crafter, "wooden puppet", knife, wood)
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
@ -259,7 +259,7 @@ parent class and have your recipes inherit from this.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from random import randint
|
from random import randint
|
||||||
from evennia.contrib.crafting.crafting import CraftingRecipe
|
from evennia.contrib.game_systems.crafting import CraftingRecipe
|
||||||
|
|
||||||
class SkillRecipe(CraftingRecipe):
|
class SkillRecipe(CraftingRecipe):
|
||||||
"""A recipe that considers skill"""
|
"""A recipe that considers skill"""
|
||||||
|
|
|
||||||
|
|
@ -16,11 +16,12 @@ In more detail, in `mygame/commands/default_cmdsets.py`:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
...
|
...
|
||||||
from evennia.contrib import extended_room # <---
|
from evennia.contrib.grid import extended_room # <---
|
||||||
|
|
||||||
class CharacterCmdset(default_cmds.Character_CmdSet):
|
class CharacterCmdset(default_cmds.CharacterCmdSet):
|
||||||
...
|
...
|
||||||
def at_cmdset_creation(self):
|
def at_cmdset_creation(self):
|
||||||
|
super().at_cmdset_creation()
|
||||||
...
|
...
|
||||||
self.add(extended_room.ExtendedRoomCmdSet) # <---
|
self.add(extended_room.ExtendedRoomCmdSet) # <---
|
||||||
|
|
||||||
|
|
@ -28,7 +29,10 @@ class CharacterCmdset(default_cmds.Character_CmdSet):
|
||||||
|
|
||||||
Then reload to make the new commands available. Note that they only work
|
Then reload to make the new commands available. Note that they only work
|
||||||
on rooms with the typeclass `ExtendedRoom`. Create new rooms with the right
|
on rooms with the typeclass `ExtendedRoom`. Create new rooms with the right
|
||||||
typeclass or use the `typeclass` command to swap existing rooms.
|
typeclass or use the `typeclass` command to swap existing rooms. Note that since
|
||||||
|
this contrib overrides the `look` command, you will need to add the
|
||||||
|
`extended_room.ExtendedRoomCmdSet` to the default character cmdset *after*
|
||||||
|
super().at_cmdset_creation(), or it will be overridden by the default look.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ Specifically, in `mygame/commands/default_cmdsets.py`:
|
||||||
...
|
...
|
||||||
from evennia.contrib.grid.ingame_map_display import MapDisplayCmdSet # <---
|
from evennia.contrib.grid.ingame_map_display import MapDisplayCmdSet # <---
|
||||||
|
|
||||||
class CharacterCmdset(default_cmds.Character_CmdSet):
|
class CharacterCmdset(default_cmds.CharacterCmdSet):
|
||||||
...
|
...
|
||||||
def at_cmdset_creation(self):
|
def at_cmdset_creation(self):
|
||||||
...
|
...
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,6 @@
|
||||||
XYZGrid - Griatch 2021
|
XYZGrid - Griatch 2021
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
from . import example, launchcmd, prototypes, tests, utils, xymap, xymap_legend, xyzgrid, xyzroom
|
||||||
|
|
||||||
from . import commands # noqa
|
from . import commands # isort:skip - this needs to be imported last
|
||||||
from . import example # noqa
|
|
||||||
from . import launchcmd # noqa
|
|
||||||
from . import prototypes # noqa
|
|
||||||
from . import tests # noqa
|
|
||||||
from . import utils # noqa
|
|
||||||
from . import xymap # noqa
|
|
||||||
from . import xymap_legend # noqa
|
|
||||||
from . import xyzgrid # noqa
|
|
||||||
from . import xyzroom # noqa
|
|
||||||
|
|
|
||||||
|
|
@ -463,7 +463,10 @@ class XYZRoom(DefaultRoom):
|
||||||
)
|
)
|
||||||
|
|
||||||
sessions = looker.sessions.get()
|
sessions = looker.sessions.get()
|
||||||
client_width, _ = sessions[0].get_client_size() if sessions else CLIENT_DEFAULT_WIDTH
|
if sessions:
|
||||||
|
client_width, _ = sessions[0].get_client_size()
|
||||||
|
else:
|
||||||
|
client_width = CLIENT_DEFAULT_WIDTH
|
||||||
|
|
||||||
map_width = xymap.max_x
|
map_width = xymap.max_x
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -166,7 +166,7 @@ This module adds no new commands; embed it in your say/emote/whisper commands.
|
||||||
### Usage:
|
### Usage:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from evennia.contrib import rplanguage
|
from evennia.contrib.rpg.rpsystem import rplanguage
|
||||||
|
|
||||||
# need to be done once, here we create the "default" lang
|
# need to be done once, here we create the "default" lang
|
||||||
rplanguage.add_language()
|
rplanguage.add_language()
|
||||||
|
|
|
||||||
|
|
@ -128,7 +128,6 @@ class EvAdventureDungeonRoom(EvAdventureRoom):
|
||||||
class EvAdventureDungeonExit(DefaultExit):
|
class EvAdventureDungeonExit(DefaultExit):
|
||||||
"""
|
"""
|
||||||
Dungeon exit. This will not create the target room until it's traversed.
|
Dungeon exit. This will not create the target room until it's traversed.
|
||||||
It must be created referencing the dungeon_orchestrator it belongs to.
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
@ -142,7 +141,8 @@ class EvAdventureDungeonExit(DefaultExit):
|
||||||
def at_traverse(self, traversing_object, target_location, **kwargs):
|
def at_traverse(self, traversing_object, target_location, **kwargs):
|
||||||
"""
|
"""
|
||||||
Called when traversing. `target_location` will be None if the
|
Called when traversing. `target_location` will be None if the
|
||||||
target was not yet created.
|
target was not yet created. It checks the current location to get the
|
||||||
|
dungeon-orchestrator in use.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if target_location == self.location:
|
if target_location == self.location:
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ object with its own functionality and state tracking.
|
||||||
|
|
||||||
Create the button with
|
Create the button with
|
||||||
|
|
||||||
create/drop button:tutorials.red_button.RedButton
|
create/drop button:contrib.tutorials.red_button.RedButton
|
||||||
|
|
||||||
Note that you must drop the button before you can see its messages! It's
|
Note that you must drop the button before you can see its messages! It's
|
||||||
imperative that you press the red button. You know you want to.
|
imperative that you press the red button. You know you want to.
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ Evmenu.
|
||||||
|
|
||||||
Log in as superuser (#1), then run
|
Log in as superuser (#1), then run
|
||||||
|
|
||||||
batchcommand tutorials.tutorial_world.build
|
batchcommand contrib.tutorials.tutorial_world.build
|
||||||
|
|
||||||
Wait a little while for building to complete and don't run the command
|
Wait a little while for building to complete and don't run the command
|
||||||
again even if it's slow. This builds the world and connect it to Limbo
|
again even if it's slow. This builds the world and connect it to Limbo
|
||||||
|
|
|
||||||
|
|
@ -31,25 +31,27 @@ HELP_ENTRY_DICTS = [
|
||||||
"category": "General",
|
"category": "General",
|
||||||
"locks": "read:perm(Developer)",
|
"locks": "read:perm(Developer)",
|
||||||
"text": """
|
"text": """
|
||||||
Evennia is a MUD game server in Python.
|
Evennia is a MU-game server and framework written in Python. You can read more
|
||||||
|
on https://www.evennia.com.
|
||||||
|
|
||||||
# subtopics
|
# subtopics
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
You'll find installation instructions on https:evennia.com
|
You'll find installation instructions on https://www.evennia.com.
|
||||||
|
|
||||||
## Community
|
## Community
|
||||||
|
|
||||||
There are many ways to get help and communicate with other devs!
|
There are many ways to get help and communicate with other devs!
|
||||||
|
|
||||||
### IRC
|
### Discussions
|
||||||
|
|
||||||
The irc channel is #evennia on irc.freenode.net
|
The Discussions forum is found at https://github.com/evennia/evennia/discussions.
|
||||||
|
|
||||||
### Discord
|
### Discord
|
||||||
|
|
||||||
There is also a discord channel you can find from the sidebard on evennia.com.
|
There is also a discord channel for chatting - connect using the
|
||||||
|
following link: https://discord.gg/AJJpcRUhtF
|
||||||
|
|
||||||
""",
|
""",
|
||||||
},
|
},
|
||||||
|
|
@ -58,7 +60,7 @@ HELP_ENTRY_DICTS = [
|
||||||
"category": "building",
|
"category": "building",
|
||||||
"text": """
|
"text": """
|
||||||
Evennia comes with a bunch of default building commands. You can
|
Evennia comes with a bunch of default building commands. You can
|
||||||
find a building tutorial in the evennia documentation.
|
find a beginner tutorial in the Evennia documentation.
|
||||||
|
|
||||||
""",
|
""",
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -8,7 +8,7 @@ msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2022-10-29 18:53+0000\n"
|
"POT-Creation-Date: 2022-10-29 18:53+0000\n"
|
||||||
"PO-Revision-Date: 2022-03-20 19:55+0100\n"
|
"PO-Revision-Date: 2022-12-16 15:09+0100\n"
|
||||||
"Last-Translator: Christophe Petry <toktoktheeo@outlook.com>\n"
|
"Last-Translator: Christophe Petry <toktoktheeo@outlook.com>\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
"Language: fr\n"
|
"Language: fr\n"
|
||||||
|
|
@ -16,7 +16,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||||
"X-Generator: Poedit 3.0.1\n"
|
"X-Generator: Poedit 3.2.2\n"
|
||||||
|
|
||||||
#: accounts/accounts.py:341
|
#: accounts/accounts.py:341
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
|
|
@ -28,6 +28,8 @@ msgstr "|c{key}|R est déjà contrôlé par un autre compte."
|
||||||
msgid ""
|
msgid ""
|
||||||
"You cannot control any more puppets (max {_MAX_NR_SIMULTANEOUS_PUPPETS})"
|
"You cannot control any more puppets (max {_MAX_NR_SIMULTANEOUS_PUPPETS})"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Vous ne pouvez contrôler plus de poupées (Maximum : "
|
||||||
|
"{_MAX_NR_SIMULTANEOUS_PUPPETS})"
|
||||||
|
|
||||||
#: accounts/accounts.py:555
|
#: accounts/accounts.py:555
|
||||||
msgid "Too many login failures; please try again in a few minutes."
|
msgid "Too many login failures; please try again in a few minutes."
|
||||||
|
|
@ -73,9 +75,8 @@ msgstr ""
|
||||||
"problème persiste."
|
"problème persiste."
|
||||||
|
|
||||||
#: accounts/accounts.py:918
|
#: accounts/accounts.py:918
|
||||||
#, fuzzy
|
|
||||||
msgid "Account being deleted."
|
msgid "Account being deleted."
|
||||||
msgstr "Suppression du compte."
|
msgstr "Le compte a été supprimé."
|
||||||
|
|
||||||
#: accounts/accounts.py:1475 accounts/accounts.py:1819
|
#: accounts/accounts.py:1475 accounts/accounts.py:1819
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
|
|
@ -382,12 +383,12 @@ msgstr "Vous avez maintenant {name} en votre possession."
|
||||||
#: objects/objects.py:1863
|
#: objects/objects.py:1863
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "{object} arrives to {destination} from {origin}."
|
msgid "{object} arrives to {destination} from {origin}."
|
||||||
msgstr ""
|
msgstr "{object} arrive à {destination} depuis {origin}."
|
||||||
|
|
||||||
#: objects/objects.py:1865
|
#: objects/objects.py:1865
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "{object} arrives to {destination}."
|
msgid "{object} arrives to {destination}."
|
||||||
msgstr ""
|
msgstr "{object} arrive à {destination}."
|
||||||
|
|
||||||
#: objects/objects.py:2530
|
#: objects/objects.py:2530
|
||||||
msgid "Invalid character name."
|
msgid "Invalid character name."
|
||||||
|
|
@ -421,10 +422,9 @@ msgid "{name} has entered the game."
|
||||||
msgstr "{name} est entré(e) dans le jeu."
|
msgstr "{name} est entré(e) dans le jeu."
|
||||||
|
|
||||||
#: objects/objects.py:2716
|
#: objects/objects.py:2716
|
||||||
#, fuzzy, python-brace-format
|
#, python-brace-format
|
||||||
#| msgid "{name} has left the game."
|
|
||||||
msgid "{name} has left the game{reason}."
|
msgid "{name} has left the game{reason}."
|
||||||
msgstr "{name} est sorti(e) du jeu."
|
msgstr "{name} est sorti(e) du jeu ({reason})."
|
||||||
|
|
||||||
#: objects/objects.py:2838
|
#: objects/objects.py:2838
|
||||||
msgid "This is a room."
|
msgid "This is a room."
|
||||||
|
|
@ -552,6 +552,8 @@ msgid ""
|
||||||
"Diff contains non-dicts that are not on the form (old, new, action_to_take): "
|
"Diff contains non-dicts that are not on the form (old, new, action_to_take): "
|
||||||
"{diffpart}"
|
"{diffpart}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"\"diff\" contient des non-dicts qui ne sont pas formatés (ancien, nouveau, "
|
||||||
|
"action à prendre): {diffpart}"
|
||||||
|
|
||||||
#: scripts/scripthandler.py:51
|
#: scripts/scripthandler.py:51
|
||||||
#, fuzzy, python-brace-format
|
#, fuzzy, python-brace-format
|
||||||
|
|
@ -613,7 +615,7 @@ msgstr "délai d'inactivité dépassé"
|
||||||
|
|
||||||
#: server/server.py:177
|
#: server/server.py:177
|
||||||
msgid " (connection lost)"
|
msgid " (connection lost)"
|
||||||
msgstr ""
|
msgstr " (connexion perdue)"
|
||||||
|
|
||||||
#: server/sessionhandler.py:41
|
#: server/sessionhandler.py:41
|
||||||
msgid "Your client sent an incorrect UTF-8 sequence."
|
msgid "Your client sent an incorrect UTF-8 sequence."
|
||||||
|
|
@ -738,6 +740,8 @@ msgstr ""
|
||||||
#: utils/eveditor.py:143
|
#: utils/eveditor.py:143
|
||||||
msgid "|rNo save function defined. Buffer cannot be saved.|n"
|
msgid "|rNo save function defined. Buffer cannot be saved.|n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"|rAucune fonction d'enregistrement définie. La pile ne peut être "
|
||||||
|
"sauvegardée.|n"
|
||||||
|
|
||||||
#: utils/eveditor.py:145
|
#: utils/eveditor.py:145
|
||||||
msgid "No changes need saving"
|
msgid "No changes need saving"
|
||||||
|
|
@ -745,7 +749,7 @@ msgstr "Aucune modification ne doit être sauvegardée"
|
||||||
|
|
||||||
#: utils/eveditor.py:146
|
#: utils/eveditor.py:146
|
||||||
msgid "Exited editor."
|
msgid "Exited editor."
|
||||||
msgstr "Sortie de l'éditeur:"
|
msgstr "Sortie de l'éditeur."
|
||||||
|
|
||||||
#: utils/eveditor.py:149
|
#: utils/eveditor.py:149
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
|
|
@ -755,6 +759,10 @@ msgid ""
|
||||||
"\n"
|
"\n"
|
||||||
"|rQuit function gave an error. Skipping.|n\n"
|
"|rQuit function gave an error. Skipping.|n\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"\n"
|
||||||
|
"{error}\n"
|
||||||
|
"\n"
|
||||||
|
"|rLa fonction quitter à retourner une erreur. On passe.|n\n"
|
||||||
|
|
||||||
#: utils/eveditor.py:157
|
#: utils/eveditor.py:157
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
|
|
@ -766,6 +774,13 @@ msgid ""
|
||||||
"to non-persistent mode (which means the editor session won't survive\n"
|
"to non-persistent mode (which means the editor session won't survive\n"
|
||||||
"an eventual server reload - so save often!)|n\n"
|
"an eventual server reload - so save often!)|n\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"\n"
|
||||||
|
"{error}\n"
|
||||||
|
"\n"
|
||||||
|
"L'éditeur n'a pas pu sauvergarder en mode persistent. Changement pour le "
|
||||||
|
"mode non-persistant. \n"
|
||||||
|
"Cela signifie que l'éditeur ne survivra pas à un rechargement du serveur, \n"
|
||||||
|
"alors sauvegardez souvent !\n"
|
||||||
|
|
||||||
#: utils/eveditor.py:167
|
#: utils/eveditor.py:167
|
||||||
msgid ""
|
msgid ""
|
||||||
|
|
@ -773,26 +788,29 @@ msgid ""
|
||||||
"EvEditor callbacks could not be pickled, for example because it's a class "
|
"EvEditor callbacks could not be pickled, for example because it's a class "
|
||||||
"method or is defined inside another function."
|
"method or is defined inside another function."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"EvEditeur erreur du mode persistant. Usuellement, c'est lorsque un ou "
|
||||||
|
"plusieurs appel n'ont pu aboutir dans l'éditeur. Par exemple, c'est "
|
||||||
|
"parcequ'une méthode de class et définie à l'intérieur d'une autre fonction."
|
||||||
|
|
||||||
#: utils/eveditor.py:173
|
#: utils/eveditor.py:173
|
||||||
msgid "Nothing to undo."
|
msgid "Nothing to undo."
|
||||||
msgstr ""
|
msgstr "Rien pour revenir en arrière."
|
||||||
|
|
||||||
#: utils/eveditor.py:174
|
#: utils/eveditor.py:174
|
||||||
msgid "Nothing to redo."
|
msgid "Nothing to redo."
|
||||||
msgstr ""
|
msgstr "Rien à rétablir."
|
||||||
|
|
||||||
#: utils/eveditor.py:175
|
#: utils/eveditor.py:175
|
||||||
msgid "Undid one step."
|
msgid "Undid one step."
|
||||||
msgstr ""
|
msgstr "Un pas supprimé."
|
||||||
|
|
||||||
#: utils/eveditor.py:176
|
#: utils/eveditor.py:176
|
||||||
msgid "Redid one step."
|
msgid "Redid one step."
|
||||||
msgstr ""
|
msgstr "Un pas ajouté."
|
||||||
|
|
||||||
#: utils/eveditor.py:494
|
#: utils/eveditor.py:494
|
||||||
msgid "Single ':' added to buffer."
|
msgid "Single ':' added to buffer."
|
||||||
msgstr ""
|
msgstr "Un seul ':' ajouté à la pile."
|
||||||
|
|
||||||
#: utils/eveditor.py:509
|
#: utils/eveditor.py:509
|
||||||
msgid "Save before quitting?"
|
msgid "Save before quitting?"
|
||||||
|
|
@ -806,7 +824,7 @@ msgstr ""
|
||||||
#: utils/eveditor.py:529
|
#: utils/eveditor.py:529
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Deleted {string}."
|
msgid "Deleted {string}."
|
||||||
msgstr ""
|
msgstr "{string} supprimé."
|
||||||
|
|
||||||
#: utils/eveditor.py:534
|
#: utils/eveditor.py:534
|
||||||
msgid "You must give a search word to delete."
|
msgid "You must give a search word to delete."
|
||||||
|
|
@ -815,17 +833,17 @@ msgstr "Vous devez donner un mot de recherche à supprimer."
|
||||||
#: utils/eveditor.py:540
|
#: utils/eveditor.py:540
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Removed {arg1} for lines {l1}-{l2}."
|
msgid "Removed {arg1} for lines {l1}-{l2}."
|
||||||
msgstr ""
|
msgstr "{arg1} retiré des lignes {l1}-{l2}."
|
||||||
|
|
||||||
#: utils/eveditor.py:546
|
#: utils/eveditor.py:546
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Removed {arg1} for {line}."
|
msgid "Removed {arg1} for {line}."
|
||||||
msgstr ""
|
msgstr "{arg1} retiré de la ligne {line}"
|
||||||
|
|
||||||
#: utils/eveditor.py:562
|
#: utils/eveditor.py:562
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Cleared {nlines} lines from buffer."
|
msgid "Cleared {nlines} lines from buffer."
|
||||||
msgstr ""
|
msgstr "{nlines} lignes nettoyées depuis la pile."
|
||||||
|
|
||||||
#: utils/eveditor.py:567
|
#: utils/eveditor.py:567
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
|
|
@ -835,7 +853,7 @@ msgstr ""
|
||||||
#: utils/eveditor.py:574
|
#: utils/eveditor.py:574
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "{line}, {cbuf} cut."
|
msgid "{line}, {cbuf} cut."
|
||||||
msgstr ""
|
msgstr "{line}, {cbuf} coupée."
|
||||||
|
|
||||||
#: utils/eveditor.py:578
|
#: utils/eveditor.py:578
|
||||||
msgid "Copy buffer is empty."
|
msgid "Copy buffer is empty."
|
||||||
|
|
@ -844,7 +862,7 @@ msgstr "Le tampon de copie est vide."
|
||||||
#: utils/eveditor.py:583
|
#: utils/eveditor.py:583
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Pasted buffer {cbuf} to {line}."
|
msgid "Pasted buffer {cbuf} to {line}."
|
||||||
msgstr ""
|
msgstr "La Pile (buffer) copié de {cbuf} à {line}"
|
||||||
|
|
||||||
#: utils/eveditor.py:591
|
#: utils/eveditor.py:591
|
||||||
msgid "You need to enter a new line and where to insert it."
|
msgid "You need to enter a new line and where to insert it."
|
||||||
|
|
@ -853,7 +871,7 @@ msgstr "Vous devez saisir une nouvelle ligne et indiquer où l'insérer."
|
||||||
#: utils/eveditor.py:596
|
#: utils/eveditor.py:596
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Inserted {num} new line(s) at {line}."
|
msgid "Inserted {num} new line(s) at {line}."
|
||||||
msgstr ""
|
msgstr "{num} ligne(s) insérée(s) depuis la ligne : {line}."
|
||||||
|
|
||||||
#: utils/eveditor.py:604
|
#: utils/eveditor.py:604
|
||||||
msgid "You need to enter a replacement string."
|
msgid "You need to enter a replacement string."
|
||||||
|
|
@ -862,7 +880,7 @@ msgstr "Vous devez saisir une chaîne de remplacement."
|
||||||
#: utils/eveditor.py:609
|
#: utils/eveditor.py:609
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Replaced {num} line(s) at {line}."
|
msgid "Replaced {num} line(s) at {line}."
|
||||||
msgstr ""
|
msgstr "{num} lignes remplacées à partir de la ligne {line}."
|
||||||
|
|
||||||
#: utils/eveditor.py:616
|
#: utils/eveditor.py:616
|
||||||
msgid "You need to enter text to insert."
|
msgid "You need to enter text to insert."
|
||||||
|
|
@ -871,16 +889,16 @@ msgstr "Vous devez saisir le texte à insérer."
|
||||||
#: utils/eveditor.py:624
|
#: utils/eveditor.py:624
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Inserted text at beginning of {line}."
|
msgid "Inserted text at beginning of {line}."
|
||||||
msgstr ""
|
msgstr "Texte ajouté au début de la ligne {line}."
|
||||||
|
|
||||||
#: utils/eveditor.py:628
|
#: utils/eveditor.py:628
|
||||||
msgid "You need to enter text to append."
|
msgid "You need to enter text to append."
|
||||||
msgstr ""
|
msgstr "Vous avez besoin d'insérer du texte à ajouter."
|
||||||
|
|
||||||
#: utils/eveditor.py:636
|
#: utils/eveditor.py:636
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Appended text to end of {line}."
|
msgid "Appended text to end of {line}."
|
||||||
msgstr ""
|
msgstr "Text ajouté à la fin de la ligne {line}."
|
||||||
|
|
||||||
#: utils/eveditor.py:641
|
#: utils/eveditor.py:641
|
||||||
msgid "You must give a search word and something to replace it with."
|
msgid "You must give a search word and something to replace it with."
|
||||||
|
|
@ -890,36 +908,36 @@ msgstr ""
|
||||||
#: utils/eveditor.py:647
|
#: utils/eveditor.py:647
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Search-replaced {arg1} -> {arg2} for lines {l1}-{l2}."
|
msgid "Search-replaced {arg1} -> {arg2} for lines {l1}-{l2}."
|
||||||
msgstr ""
|
msgstr "Rechercher-remplacer {arg1} -> {arg2} pour les lignes {l1}-{l2}."
|
||||||
|
|
||||||
#: utils/eveditor.py:653
|
#: utils/eveditor.py:653
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Search-replaced {arg1} -> {arg2} for {line}."
|
msgid "Search-replaced {arg1} -> {arg2} for {line}."
|
||||||
msgstr ""
|
msgstr "Recherche-remplacer {arg1} -> {arg2} pour la ligne {line}."
|
||||||
|
|
||||||
#: utils/eveditor.py:677
|
#: utils/eveditor.py:677
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Flood filled lines {l1}-{l2}."
|
msgid "Flood filled lines {l1}-{l2}."
|
||||||
msgstr ""
|
msgstr "Lignes remplies (inondées ?) {l1}-{l2}."
|
||||||
|
|
||||||
#: utils/eveditor.py:679
|
#: utils/eveditor.py:679
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Flood filled {line}."
|
msgid "Flood filled {line}."
|
||||||
msgstr ""
|
msgstr "\"flood\" rempli {line}."
|
||||||
|
|
||||||
#: utils/eveditor.py:701
|
#: utils/eveditor.py:701
|
||||||
msgid "Valid justifications are"
|
msgid "Valid justifications are"
|
||||||
msgstr ""
|
msgstr "Les justification validées sont"
|
||||||
|
|
||||||
#: utils/eveditor.py:710
|
#: utils/eveditor.py:710
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "{align}-justified lines {l1}-{l2}."
|
msgid "{align}-justified lines {l1}-{l2}."
|
||||||
msgstr ""
|
msgstr "{align}-lignes justifiées{l1}-{l2}."
|
||||||
|
|
||||||
#: utils/eveditor.py:716
|
#: utils/eveditor.py:716
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "{align}-justified {line}."
|
msgid "{align}-justified {line}."
|
||||||
msgstr ""
|
msgstr "{align}-justified {line}."
|
||||||
|
|
||||||
#: utils/eveditor.py:728
|
#: utils/eveditor.py:728
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
|
|
@ -976,11 +994,11 @@ msgstr "Auto-indentation désactivée."
|
||||||
#: utils/eveditor.py:1093
|
#: utils/eveditor.py:1093
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Line Editor [{name}]"
|
msgid "Line Editor [{name}]"
|
||||||
msgstr ""
|
msgstr "Édition ligne [{name}]"
|
||||||
|
|
||||||
#: utils/eveditor.py:1101
|
#: utils/eveditor.py:1101
|
||||||
msgid "(:h for help)"
|
msgid "(:h for help)"
|
||||||
msgstr ""
|
msgstr "(:h pour l'aide)"
|
||||||
|
|
||||||
#: utils/evmenu.py:302
|
#: utils/evmenu.py:302
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
|
|
@ -1026,15 +1044,15 @@ msgstr "|rChoix invalide.|n"
|
||||||
|
|
||||||
#: utils/evmenu.py:1439
|
#: utils/evmenu.py:1439
|
||||||
msgid "|Wcurrent|n"
|
msgid "|Wcurrent|n"
|
||||||
msgstr ""
|
msgstr "|WActuel|n"
|
||||||
|
|
||||||
#: utils/evmenu.py:1447
|
#: utils/evmenu.py:1447
|
||||||
msgid "|wp|Wrevious page|n"
|
msgid "|wp|Wrevious page|n"
|
||||||
msgstr ""
|
msgstr "|wp|Wage précédente|n"
|
||||||
|
|
||||||
#: utils/evmenu.py:1454
|
#: utils/evmenu.py:1454
|
||||||
msgid "|wn|Wext page|n"
|
msgid "|wn|Wext page|n"
|
||||||
msgstr ""
|
msgstr "|wp|Wpage suivante|n"
|
||||||
|
|
||||||
#: utils/evmenu.py:1689
|
#: utils/evmenu.py:1689
|
||||||
msgid "Aborted."
|
msgid "Aborted."
|
||||||
|
|
|
||||||
|
|
@ -538,8 +538,16 @@ def _get_twistd_cmdline(pprofiler, sprofiler):
|
||||||
Compile the command line for starting a Twisted application using the 'twistd' executable.
|
Compile the command line for starting a Twisted application using the 'twistd' executable.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
portal_cmd = [TWISTED_BINARY, "--python={}".format(PORTAL_PY_FILE)]
|
portal_cmd = [
|
||||||
server_cmd = [TWISTED_BINARY, "--python={}".format(SERVER_PY_FILE)]
|
TWISTED_BINARY,
|
||||||
|
f"--python={PORTAL_PY_FILE}",
|
||||||
|
"--logger=evennia.utils.logger.GetPortalLogObserver",
|
||||||
|
]
|
||||||
|
server_cmd = [
|
||||||
|
TWISTED_BINARY,
|
||||||
|
f"--python={SERVER_PY_FILE}",
|
||||||
|
"--logger=evennia.utils.logger.GetServerLogObserver",
|
||||||
|
]
|
||||||
|
|
||||||
if os.name != "nt":
|
if os.name != "nt":
|
||||||
# PID files only for UNIX
|
# PID files only for UNIX
|
||||||
|
|
@ -1363,8 +1371,8 @@ def set_gamedir(path):
|
||||||
global GAMEDIR
|
global GAMEDIR
|
||||||
|
|
||||||
Ndepth = 10
|
Ndepth = 10
|
||||||
settings_path = os.path.join("server", "conf", "settings.py")
|
settings_path = SETTINGS_DOTPATH.replace(".", os.sep) + ".py"
|
||||||
os.chdir(GAMEDIR)
|
os.chdir(path)
|
||||||
for i in range(Ndepth):
|
for i in range(Ndepth):
|
||||||
gpath = os.getcwd()
|
gpath = os.getcwd()
|
||||||
if "server" in os.listdir(gpath):
|
if "server" in os.listdir(gpath):
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ def should_retry(status_code):
|
||||||
|
|
||||||
class DiscordWebsocketServerFactory(WebSocketClientFactory, protocol.ReconnectingClientFactory):
|
class DiscordWebsocketServerFactory(WebSocketClientFactory, protocol.ReconnectingClientFactory):
|
||||||
"""
|
"""
|
||||||
A variant of the websocket-factory that auto-reconnects.
|
A customized websocket client factory that navigates the Discord gateway process.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
@ -94,7 +94,7 @@ class DiscordWebsocketServerFactory(WebSocketClientFactory, protocol.Reconnectin
|
||||||
noisy = False
|
noisy = False
|
||||||
gateway = None
|
gateway = None
|
||||||
resume_url = None
|
resume_url = None
|
||||||
do_retry = True
|
is_connecting = False
|
||||||
|
|
||||||
def __init__(self, sessionhandler, *args, **kwargs):
|
def __init__(self, sessionhandler, *args, **kwargs):
|
||||||
self.uid = kwargs.get("uid")
|
self.uid = kwargs.get("uid")
|
||||||
|
|
@ -122,8 +122,8 @@ class DiscordWebsocketServerFactory(WebSocketClientFactory, protocol.Reconnectin
|
||||||
d = readBody(response)
|
d = readBody(response)
|
||||||
d.addCallback(self.websocket_init, *args, **kwargs)
|
d.addCallback(self.websocket_init, *args, **kwargs)
|
||||||
return d
|
return d
|
||||||
elif should_retry(response.code):
|
else:
|
||||||
delay(300, self.get_gateway_url, *args, **kwargs)
|
logger.log_warn("Discord gateway request failed.")
|
||||||
|
|
||||||
d.addCallback(cbResponse)
|
d.addCallback(cbResponse)
|
||||||
|
|
||||||
|
|
@ -132,6 +132,7 @@ class DiscordWebsocketServerFactory(WebSocketClientFactory, protocol.Reconnectin
|
||||||
callback for when the URL is gotten
|
callback for when the URL is gotten
|
||||||
"""
|
"""
|
||||||
data = json.loads(str(payload, "utf-8"))
|
data = json.loads(str(payload, "utf-8"))
|
||||||
|
self.is_connecting = False
|
||||||
if url := data.get("url"):
|
if url := data.get("url"):
|
||||||
self.gateway = f"{url}/?v={DISCORD_API_VERSION}&encoding=json".encode("utf-8")
|
self.gateway = f"{url}/?v={DISCORD_API_VERSION}&encoding=json".encode("utf-8")
|
||||||
useragent = kwargs.pop("useragent", DISCORD_USER_AGENT)
|
useragent = kwargs.pop("useragent", DISCORD_USER_AGENT)
|
||||||
|
|
@ -179,30 +180,7 @@ class DiscordWebsocketServerFactory(WebSocketClientFactory, protocol.Reconnectin
|
||||||
connector (Connector): Represents the connection.
|
connector (Connector): Represents the connection.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
logger.log_info("Attempting connection to Discord...")
|
logger.log_info("Connecting to Discord...")
|
||||||
|
|
||||||
def clientConnectionFailed(self, connector, reason):
|
|
||||||
"""
|
|
||||||
Called when Client failed to connect.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
connector (Connection): Represents the connection.
|
|
||||||
reason (str): The reason for the failure.
|
|
||||||
|
|
||||||
"""
|
|
||||||
protocol.ReconnectingClientFactory.clientConnectionLost(self, connector, reason)
|
|
||||||
|
|
||||||
def clientConnectionLost(self, connector, reason):
|
|
||||||
"""
|
|
||||||
Called when Client loses connection.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
connector (Connection): Represents the connection.
|
|
||||||
reason (str): The reason for the failure.
|
|
||||||
|
|
||||||
"""
|
|
||||||
if self.do_retry or not self.bot:
|
|
||||||
self.retry(connector)
|
|
||||||
|
|
||||||
def reconnect(self):
|
def reconnect(self):
|
||||||
"""
|
"""
|
||||||
|
|
@ -210,33 +188,30 @@ class DiscordWebsocketServerFactory(WebSocketClientFactory, protocol.Reconnectin
|
||||||
de-registering the session and then reattaching a new one.
|
de-registering the session and then reattaching a new one.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
# set the retry flag to False so it doesn't attempt an automatic retry
|
|
||||||
# and duplicate the connection
|
|
||||||
self.do_retry = False
|
|
||||||
# disconnect everything
|
|
||||||
self.bot.transport.loseConnection()
|
|
||||||
self.sessionhandler.server_disconnect(self.bot)
|
|
||||||
# set up the reconnection
|
# set up the reconnection
|
||||||
if self.resume_url:
|
if self.resume_url:
|
||||||
self.url = self.resume_url
|
self.url = self.resume_url
|
||||||
elif self.gateway:
|
elif self.gateway:
|
||||||
self.url = self.gateway
|
self.url = self.gateway
|
||||||
else:
|
else:
|
||||||
# we don't know where to reconnect to! start from the beginning
|
# we don't know where to reconnect to! we'll start from the beginning
|
||||||
self.get_gateway_url()
|
self.url = None
|
||||||
return
|
# reset the internal delay, since this is a deliberate disconnect
|
||||||
self.start()
|
self.delay = self.initialDelay
|
||||||
|
# disconnect to allow the reconnection process to kick in
|
||||||
|
self.bot.sendClose()
|
||||||
|
self.sessionhandler.server_disconnect(self.bot)
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
"Connect protocol to remote server"
|
"Connect protocol to remote server"
|
||||||
|
|
||||||
if not self.gateway:
|
if not self.gateway:
|
||||||
# we can't actually start yet
|
# we don't know where to connect to
|
||||||
# get the gateway URL from Discord
|
# get the gateway URL from Discord
|
||||||
|
self.is_connecting = True
|
||||||
self.get_gateway_url()
|
self.get_gateway_url()
|
||||||
else:
|
elif not self.is_connecting:
|
||||||
# set the retry flag so we maintain this connection
|
# everything is good, connect
|
||||||
self.do_retry = True
|
|
||||||
connectWS(self)
|
connectWS(self)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -255,7 +230,6 @@ class DiscordClient(WebSocketClientProtocol, _BASE_SESSION_CLASS):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
WebSocketClientProtocol.__init__(self)
|
WebSocketClientProtocol.__init__(self)
|
||||||
_BASE_SESSION_CLASS.__init__(self)
|
_BASE_SESSION_CLASS.__init__(self)
|
||||||
self.restart_downtime = None
|
|
||||||
|
|
||||||
def at_login(self):
|
def at_login(self):
|
||||||
pass
|
pass
|
||||||
|
|
@ -265,8 +239,7 @@ class DiscordClient(WebSocketClientProtocol, _BASE_SESSION_CLASS):
|
||||||
Called when connection is established.
|
Called when connection is established.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
self.restart_downtime = None
|
logger.log_msg("Discord connection established.")
|
||||||
self.restart_task = None
|
|
||||||
self.factory.bot = self
|
self.factory.bot = self
|
||||||
|
|
||||||
self.init_session("discord", "discord.gg", self.factory.sessionhandler)
|
self.init_session("discord", "discord.gg", self.factory.sessionhandler)
|
||||||
|
|
@ -352,11 +325,11 @@ class DiscordClient(WebSocketClientProtocol, _BASE_SESSION_CLASS):
|
||||||
"""
|
"""
|
||||||
if self.nextHeartbeatCall:
|
if self.nextHeartbeatCall:
|
||||||
self.nextHeartbeatCall.cancel()
|
self.nextHeartbeatCall.cancel()
|
||||||
self.disconnect(reason)
|
self.nextHeartbeatCall = None
|
||||||
if code >= 4000:
|
if wasClean:
|
||||||
logger.log_err(f"Discord connection closed: {reason}")
|
logger.log_info(f"Discord connection closed ({code}) reason: {reason}")
|
||||||
else:
|
else:
|
||||||
logger.log_info(f"Discord disconnected: {reason}")
|
logger.log_info(f"Discord connection lost.")
|
||||||
|
|
||||||
def _send_json(self, data):
|
def _send_json(self, data):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -68,27 +68,27 @@ class TestLauncher(TwistedTestCase):
|
||||||
@patch("evennia.server.evennia_launcher.os.name", new="posix")
|
@patch("evennia.server.evennia_launcher.os.name", new="posix")
|
||||||
def test_get_twisted_cmdline(self):
|
def test_get_twisted_cmdline(self):
|
||||||
pcmd, scmd = evennia_launcher._get_twistd_cmdline(False, False)
|
pcmd, scmd = evennia_launcher._get_twistd_cmdline(False, False)
|
||||||
self.assertTrue("portal.py" in pcmd[1])
|
self.assertIn("portal.py", pcmd[1])
|
||||||
self.assertTrue("--pidfile" in pcmd[2])
|
self.assertIn("--pidfile", pcmd[3])
|
||||||
self.assertTrue("server.py" in scmd[1])
|
self.assertIn("server.py", scmd[1])
|
||||||
self.assertTrue("--pidfile" in scmd[2])
|
self.assertIn("--pidfile", scmd[3])
|
||||||
|
|
||||||
pcmd, scmd = evennia_launcher._get_twistd_cmdline(True, True)
|
pcmd, scmd = evennia_launcher._get_twistd_cmdline(True, True)
|
||||||
self.assertTrue("portal.py" in pcmd[1])
|
self.assertIn("portal.py", pcmd[1])
|
||||||
self.assertTrue("--pidfile" in pcmd[2])
|
self.assertIn("--pidfile", pcmd[3])
|
||||||
self.assertTrue("--profiler=cprofile" in pcmd[4], "actual: {}".format(pcmd))
|
self.assertIn("--profiler=cprofile", pcmd[5], pcmd)
|
||||||
self.assertTrue("--profile=" in pcmd[5])
|
self.assertIn("--profile=", pcmd[6])
|
||||||
self.assertTrue("server.py" in scmd[1])
|
self.assertIn("server.py", scmd[1])
|
||||||
self.assertTrue("--pidfile" in scmd[2])
|
self.assertIn("--pidfile", scmd[3])
|
||||||
self.assertTrue("--pidfile" in scmd[2])
|
self.assertIn("--pidfile", scmd[3])
|
||||||
self.assertTrue("--profiler=cprofile" in scmd[4], "actual: {}".format(scmd))
|
self.assertIn("--profiler=cprofile", scmd[5], "actual: {}".format(scmd))
|
||||||
self.assertTrue("--profile=" in scmd[5])
|
self.assertIn("--profile=", scmd[6])
|
||||||
|
|
||||||
@patch("evennia.server.evennia_launcher.os.name", new="nt")
|
@patch("evennia.server.evennia_launcher.os.name", new="nt")
|
||||||
def test_get_twisted_cmdline_nt(self):
|
def test_get_twisted_cmdline_nt(self):
|
||||||
pcmd, scmd = evennia_launcher._get_twistd_cmdline(False, False)
|
pcmd, scmd = evennia_launcher._get_twistd_cmdline(False, False)
|
||||||
self.assertTrue(len(pcmd) == 2, "actual: {}".format(pcmd))
|
self.assertTrue(len(pcmd) == 3, pcmd)
|
||||||
self.assertTrue(len(scmd) == 2, "actual: {}".format(scmd))
|
self.assertTrue(len(scmd) == 3, scmd)
|
||||||
|
|
||||||
@patch("evennia.server.evennia_launcher.reactor.stop")
|
@patch("evennia.server.evennia_launcher.reactor.stop")
|
||||||
def test_reactor_stop(self, mockstop):
|
def test_reactor_stop(self, mockstop):
|
||||||
|
|
|
||||||
|
|
@ -1737,7 +1737,7 @@ class NickHandler(AttributeHandler):
|
||||||
regex = re.compile(nick_regex, re.I + re.DOTALL + re.U)
|
regex = re.compile(nick_regex, re.I + re.DOTALL + re.U)
|
||||||
self._regex_cache[nick_regex] = regex
|
self._regex_cache[nick_regex] = regex
|
||||||
|
|
||||||
is_match, raw_string = parse_nick_template(raw_string.strip(), regex, template)
|
is_match, raw_string = parse_nick_template(raw_string, regex, template)
|
||||||
if is_match:
|
if is_match:
|
||||||
break
|
break
|
||||||
return raw_string
|
return raw_string
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ except ImportError:
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
from django.utils.safestring import SafeString
|
from django.utils.safestring import SafeString
|
||||||
|
|
||||||
from evennia.utils import logger
|
from evennia.utils import logger
|
||||||
from evennia.utils.utils import is_iter, to_bytes, uses_database
|
from evennia.utils.utils import is_iter, to_bytes, uses_database
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -273,22 +273,12 @@ from django.conf import settings
|
||||||
|
|
||||||
# i18n
|
# i18n
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
|
|
||||||
from evennia import CmdSet, Command
|
from evennia import CmdSet, Command
|
||||||
from evennia.commands import cmdhandler
|
from evennia.commands import cmdhandler
|
||||||
from evennia.utils import logger
|
from evennia.utils import logger
|
||||||
from evennia.utils.ansi import strip_ansi
|
from evennia.utils.ansi import strip_ansi
|
||||||
from evennia.utils.evtable import EvColumn, EvTable
|
from evennia.utils.evtable import EvColumn, EvTable
|
||||||
from evennia.utils.utils import (
|
from evennia.utils.utils import crop, dedent, is_iter, m_len, make_iter, mod_import, pad, to_str
|
||||||
crop,
|
|
||||||
dedent,
|
|
||||||
is_iter,
|
|
||||||
m_len,
|
|
||||||
make_iter,
|
|
||||||
mod_import,
|
|
||||||
pad,
|
|
||||||
to_str,
|
|
||||||
)
|
|
||||||
|
|
||||||
# read from protocol NAWS later?
|
# read from protocol NAWS later?
|
||||||
_MAX_TEXT_WIDTH = settings.CLIENT_DEFAULT_WIDTH
|
_MAX_TEXT_WIDTH = settings.CLIENT_DEFAULT_WIDTH
|
||||||
|
|
|
||||||
|
|
@ -288,8 +288,8 @@ def justify(text, width=None, align="l", indent=0, fillchar=" "):
|
||||||
# absolute mode - just crop or fill to width
|
# absolute mode - just crop or fill to width
|
||||||
abs_lines = []
|
abs_lines = []
|
||||||
for line in text.split("\n"):
|
for line in text.split("\n"):
|
||||||
nlen = len(line)
|
nlen = m_len(line)
|
||||||
if len(line) < width:
|
if m_len(line) < width:
|
||||||
line += sp * (width - nlen)
|
line += sp * (width - nlen)
|
||||||
else:
|
else:
|
||||||
line = crop(line, width=width, suffix="")
|
line = crop(line, width=width, suffix="")
|
||||||
|
|
@ -304,7 +304,7 @@ def justify(text, width=None, align="l", indent=0, fillchar=" "):
|
||||||
for ip, paragraph in enumerate(paragraphs):
|
for ip, paragraph in enumerate(paragraphs):
|
||||||
if ip > 0:
|
if ip > 0:
|
||||||
words.append(("\n", 0))
|
words.append(("\n", 0))
|
||||||
words.extend((word, len(word)) for word in paragraph.split())
|
words.extend((word, m_len(word)) for word in paragraph.split())
|
||||||
|
|
||||||
if not words:
|
if not words:
|
||||||
# Just whitespace!
|
# Just whitespace!
|
||||||
|
|
|
||||||
184
pyproject.toml
184
pyproject.toml
|
|
@ -4,98 +4,117 @@ build-backend = "setuptools.build_meta"
|
||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "evennia"
|
name = "evennia"
|
||||||
version = "1.0rc11"
|
version = "1.0.2"
|
||||||
maintainers = [
|
maintainers = [{ name = "Griatch", email = "griatch@gmail.com" }]
|
||||||
{ name="Griatch", email="griatch@gmail.com" },
|
|
||||||
]
|
|
||||||
description = "A full-featured toolkit and server for text-based multiplayer games (MUDs, MU*, etc)."
|
description = "A full-featured toolkit and server for text-based multiplayer games (MUDs, MU*, etc)."
|
||||||
requires-python = ">=3.10"
|
requires-python = ">=3.10"
|
||||||
readme = { file="README.md", content-type="text/markdown" }
|
readme = { file = "README.md", content-type = "text/markdown" }
|
||||||
license = { text="BSD" }
|
license = { text = "BSD" }
|
||||||
keywords = [
|
keywords = [
|
||||||
"MUD", "MUSH", "MUX", "MMO", "text-only", "multiplayer", "online", "rpg", "game", "engine",
|
"MUD",
|
||||||
"framework", "text", "adventure", "telnet", "websocket", "blind", "accessible", "ascii",
|
"MUSH",
|
||||||
"utf-8", "terminal", "online", "server", "beginner", "tutorials"
|
"MUX",
|
||||||
|
"MMO",
|
||||||
|
"text-only",
|
||||||
|
"multiplayer",
|
||||||
|
"online",
|
||||||
|
"rpg",
|
||||||
|
"game",
|
||||||
|
"engine",
|
||||||
|
"framework",
|
||||||
|
"text",
|
||||||
|
"adventure",
|
||||||
|
"telnet",
|
||||||
|
"websocket",
|
||||||
|
"blind",
|
||||||
|
"accessible",
|
||||||
|
"ascii",
|
||||||
|
"utf-8",
|
||||||
|
"terminal",
|
||||||
|
"online",
|
||||||
|
"server",
|
||||||
|
"beginner",
|
||||||
|
"tutorials",
|
||||||
]
|
]
|
||||||
classifiers = [
|
classifiers = [
|
||||||
"Programming Language :: Python :: 3 :: Only",
|
"Programming Language :: Python :: 3 :: Only",
|
||||||
"Programming Language :: Python :: 3.10",
|
"Programming Language :: Python :: 3.10",
|
||||||
"Programming Language :: Python :: 3.11",
|
"Programming Language :: Python :: 3.11",
|
||||||
"Programming Language :: JavaScript",
|
"Programming Language :: JavaScript",
|
||||||
"Development Status :: 5 - Production/Stable",
|
"Development Status :: 5 - Production/Stable",
|
||||||
"License :: OSI Approved :: BSD License",
|
"License :: OSI Approved :: BSD License",
|
||||||
"Environment :: Console",
|
"Environment :: Console",
|
||||||
"Environment :: Web Environment",
|
"Environment :: Web Environment",
|
||||||
"Framework :: Django",
|
"Framework :: Django",
|
||||||
"Framework :: Twisted",
|
"Framework :: Twisted",
|
||||||
"Intended Audience :: Developers",
|
"Intended Audience :: Developers",
|
||||||
"Intended Audience :: Education",
|
"Intended Audience :: Education",
|
||||||
"Operating System :: MacOS",
|
"Operating System :: MacOS",
|
||||||
"Operating System :: Microsoft :: Windows",
|
"Operating System :: Microsoft :: Windows",
|
||||||
"Operating System :: POSIX :: Linux",
|
"Operating System :: POSIX :: Linux",
|
||||||
"Topic :: Database",
|
"Topic :: Database",
|
||||||
"Topic :: Education",
|
"Topic :: Education",
|
||||||
"Topic :: Games/Entertainment :: Multi-User Dungeons (MUD)",
|
"Topic :: Games/Entertainment :: Multi-User Dungeons (MUD)",
|
||||||
"Topic :: Games/Entertainment :: Puzzle Games",
|
"Topic :: Games/Entertainment :: Puzzle Games",
|
||||||
"Topic :: Games/Entertainment :: Role-Playing",
|
"Topic :: Games/Entertainment :: Role-Playing",
|
||||||
"Topic :: Games/Entertainment :: Simulation",
|
"Topic :: Games/Entertainment :: Simulation",
|
||||||
"Topic :: Software Development :: Libraries :: Application Frameworks",
|
"Topic :: Software Development :: Libraries :: Application Frameworks",
|
||||||
"Topic :: Internet :: WWW/HTTP :: WSGI :: Server"
|
"Topic :: Internet :: WWW/HTTP :: WSGI :: Server",
|
||||||
]
|
]
|
||||||
dependencies = [
|
dependencies = [
|
||||||
# core dependencies
|
# core dependencies
|
||||||
"django >= 4.1.3, < 4.2",
|
"django >= 4.1.3, < 4.2",
|
||||||
"twisted >= 22.10, < 23",
|
"twisted >= 22.10, < 23",
|
||||||
"pytz >= 2022.6",
|
"pytz >= 2022.6",
|
||||||
"djangorestframework >= 3.14, < 3.15",
|
"djangorestframework >= 3.14, < 3.15",
|
||||||
"pyyaml >= 6.0",
|
"pyyaml >= 6.0",
|
||||||
"django-filter == 2.4",
|
"django-filter == 2.4",
|
||||||
"django-sekizai == 2.0.0",
|
"django-sekizai == 2.0.0",
|
||||||
"inflect >= 5.2.0",
|
"inflect >= 5.2.0",
|
||||||
"autobahn >= 20.7.1, < 21.0.0",
|
"autobahn >= 20.7.1, < 21.0.0",
|
||||||
"lunr == 0.6.0",
|
"lunr == 0.6.0",
|
||||||
"simpleeval <= 1.0",
|
"simpleeval <= 1.0",
|
||||||
"uritemplate == 4.1.1",
|
"uritemplate == 4.1.1",
|
||||||
"Jinja2 < 3.1",
|
"Jinja2 < 3.1",
|
||||||
"tzdata >= 2022.6",
|
"tzdata >= 2022.6",
|
||||||
# for unit tests and code formatting
|
# for unit tests and code formatting
|
||||||
"mock >= 4.0.3",
|
"mock >= 4.0.3",
|
||||||
"model_mommy >= 2.0",
|
"model_mommy >= 2.0",
|
||||||
"anything ==0.2.1",
|
"anything ==0.2.1",
|
||||||
"black >= 22.6",
|
"black >= 22.6",
|
||||||
"isort >= 5.10",
|
"isort >= 5.10",
|
||||||
"parameterized ==0.8.1",
|
"parameterized ==0.8.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[project.optional-dependencies]
|
[project.optional-dependencies]
|
||||||
|
|
||||||
extra = [
|
extra = [
|
||||||
# contrib optional dependencies
|
# contrib optional dependencies
|
||||||
# install with 'pip install evennia[extra]`
|
# install with 'pip install evennia[extra]`
|
||||||
|
|
||||||
# crypto libraries for ssh support
|
# crypto libraries for ssh support
|
||||||
"cryptography >= 2.8",
|
"cryptography >= 2.8",
|
||||||
"pyasn1 >= 0.4.8",
|
"pyasn1 >= 0.4.8",
|
||||||
"bcrypt >= 3.1.7",
|
"bcrypt >= 3.1.7",
|
||||||
|
|
||||||
# Telnet-SSL support
|
# Telnet-SSL support
|
||||||
"pyopenssl >= 19.1",
|
"pyopenssl >= 19.1",
|
||||||
"service_identity >= 18.1.0",
|
"service_identity >= 18.1.0",
|
||||||
|
|
||||||
# AWS storage contrib
|
# AWS storage contrib
|
||||||
"boto3 >= 1.4.4",
|
"boto3 >= 1.4.4",
|
||||||
"botocore >= 1.15",
|
"botocore >= 1.15",
|
||||||
|
|
||||||
# Jupyter Notebook support
|
# Jupyter Notebook support
|
||||||
"jupyter >= 1.0.0",
|
"jupyter >= 1.0.0",
|
||||||
"ipython >= 7.19.0",
|
"ipython >= 7.19.0",
|
||||||
"django-extensions >= 3.1.0",
|
"django-extensions >= 3.1.0",
|
||||||
|
|
||||||
# xyzroom contrib
|
# xyzroom contrib
|
||||||
"scipy == 1.9.3",
|
"scipy == 1.9.3",
|
||||||
|
|
||||||
# Git contrib
|
# Git contrib
|
||||||
"gitpython >= 3.1.27"
|
"gitpython >= 3.1.27",
|
||||||
]
|
]
|
||||||
|
|
||||||
[project.urls]
|
[project.urls]
|
||||||
|
|
@ -133,3 +152,20 @@ exclude = '''
|
||||||
|
|
||||||
)
|
)
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
[tool.coverage]
|
||||||
|
|
||||||
|
[tool.coverage.run]
|
||||||
|
concurrency = ["multiprocessing"]
|
||||||
|
parallel = true
|
||||||
|
source = ["evennia"]
|
||||||
|
omit = [
|
||||||
|
"*/migrations/*",
|
||||||
|
"*/urls.py",
|
||||||
|
"*/test*.py",
|
||||||
|
"*.sh",
|
||||||
|
"*.txt",
|
||||||
|
"*.md",
|
||||||
|
"*.pyc",
|
||||||
|
"*.service",
|
||||||
|
]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue