mirror of
https://github.com/evennia/evennia.git
synced 2026-04-01 13:37:17 +02:00
Add 1.x legacy docs
This commit is contained in:
parent
bcfd8e5b21
commit
bbfdf4aff0
1578 changed files with 491624 additions and 0 deletions
780
docs/1.x/_sources/Coding/Changelog.md.txt
Normal file
780
docs/1.x/_sources/Coding/Changelog.md.txt
Normal file
|
|
@ -0,0 +1,780 @@
|
|||
# Changelog
|
||||
|
||||
### 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+.
|
||||
|
||||
- New `drop:holds()` lock default to limit dropping nonsensical things. Access check
|
||||
defaults to True for backwards-compatibility in 0.9, will be False in 1.0
|
||||
- REST API allows you external access to db objects through HTTP requests (Tehom)
|
||||
- `Object.normalize_name` and `.validate_name` added to (by default) enforce latinify
|
||||
on character name and avoid potential exploits using clever Unicode chars (trhr)
|
||||
- New `utils.format_grid` for easily displaying long lists of items in a block.
|
||||
- Using `lunr` search indexing for better `help` matching and suggestions. Also improve
|
||||
the main help command's default listing output.
|
||||
- Added `content_types` indexing to DefaultObject's ContentsHandler. (volund)
|
||||
- Made most of the networking classes such as Protocols and the SessionHandlers
|
||||
replaceable via `settings.py` for modding enthusiasts. (volund)
|
||||
- The `initial_setup.py` file can now be substituted in `settings.py` to customize
|
||||
initial game database state. (volund)
|
||||
- Added new Traits contrib, converted and expanded from Ainneve project.
|
||||
- Added new `requirements_extra.txt` file for easily getting all optional dependencies.
|
||||
- Change default multi-match syntax from 1-obj, 2-obj to obj-1, obj-2.
|
||||
- Make `object.search` support 'stacks=0' keyword - if ``>0``, the method will return
|
||||
N identical matches instead of triggering a multi-match error.
|
||||
- Add `tags.has()` method for checking if an object has a tag or tags (PR by ChrisLR)
|
||||
- Make IP throttle use Django-based cache system for optional persistence (PR by strikaco)
|
||||
- Renamed Tutorial classes "Weapon" and "WeaponRack" to "TutorialWeapon" and
|
||||
"TutorialWeaponRack" to prevent collisions with classes in mygame
|
||||
- New `crafting` contrib, adding a full crafting subsystem (Griatch 2020)
|
||||
- The `rplanguage` contrib now auto-capitalizes sentences and retains ellipsis (...). This
|
||||
change means that proper nouns at the start of sentences will not be treated as nouns.
|
||||
- Make MuxCommand `lhs/rhslist` always be lists, also if empty (used to be the empty string)
|
||||
- Fix typo in UnixCommand contrib, where `help` was given as `--hel`.
|
||||
- Latin (la) i18n translation (jamalainm)
|
||||
- Made the `evennia` dir possible to use without gamedir for purpose of doc generation.
|
||||
- Make Scripts' timer component independent from script object deletion; can now start/stop
|
||||
timer without deleting Script. The `.persistent` flag now only controls if timer survives
|
||||
reload - Script has to be removed with `.delete()` like other typeclassed entities.
|
||||
- Add `utils.repeat` and `utils.unrepeat` as shortcuts to TickerHandler add/remove, similar
|
||||
to how `utils.delay` is a shortcut for TaskHandler add.
|
||||
- Refactor the classic `red_button` example to use `utils.delay/repeat` and modern recommended
|
||||
code style and paradigms instead of relying on `Scripts` for everything.
|
||||
- Expand `CommandTest` with ability to check multiple message-receivers; inspired by PR by
|
||||
user davewiththenicehat. Also add new doc string.
|
||||
- Add central `FuncParser` as a much more powerful replacement for the old `parse_inlinefunc`
|
||||
function.
|
||||
- Attribute/NAttribute got a homogenous representation, using intefaces, both
|
||||
`AttributeHandler` and `NAttributeHandler` has same api now.
|
||||
- Add `evennia/utils/verb_conjugation` for automatic verb conjugation (English only). This
|
||||
is useful for implementing actor-stance emoting for sending a string to different targets.
|
||||
- New version of Italian translation (rpolve)
|
||||
- `utils.evmenu.ask_yes_no` is a helper function that makes it easy to ask a yes/no question
|
||||
to the user and respond to their input. This complements the existing `get_input` helper.
|
||||
- Allow sending messages with `page/tell` without a `=` if target name contains no spaces.
|
||||
- New FileHelpStorage system allows adding help entries via external files.
|
||||
- `sethelp` command now warns if shadowing other help-types when creating a new
|
||||
entry.
|
||||
- Help command now uses `view` lock to determine if cmd/entry shows in index and
|
||||
`read` lock to determine if it can be read. It used to be `view` in the role
|
||||
of the latter. Migration swaps these around.
|
||||
- In modules given by `settings.PROTOTYPE_MODULES`, spawner will now first look for a global
|
||||
list `PROTOTYPE_LIST` of dicts before loading all dicts in the module as prototypes.
|
||||
- New Channel-System using the `channel` command and nicks. Removed the `ChannelHandler` and the
|
||||
concept of a dynamically created `ChannelCmdSet`.
|
||||
- Add `Msg.db_receiver_external` field to allowe external, string-id message-receivers.
|
||||
- Renamed `app.css` to `website.css` for consistency. Removed old prosimii-css files.
|
||||
- Remove `mygame/web/static_overrides` and -`template_overrides`, reorganize website/admin/client/api
|
||||
into a more consistent structure for overriding. Expanded webpage documentation considerably.
|
||||
- REST API list-view was shortened (#2401). New CSS/HTML. Add ReDoc for API autodoc page.
|
||||
- Update and fix dummyrunner with cleaner code and setup.
|
||||
- Made `iter_to_str` format prettier strings, using Oxford comma.
|
||||
- Added an MXP anchor tag to also support clickable web links.
|
||||
- New `tasks` command for managing tasks started with `utils.delay` (PR by davewiththenicehat)
|
||||
- Make `help` index output clickable for webclient/clients with MXP (PR by davewiththenicehat)
|
||||
- Custom `evennia` launcher commands (e.g. `evennia mycmd foo bar`). Add new commands as callables
|
||||
accepting `*args`, as `settings.EXTRA_LAUNCHER_COMMANDS = {'mycmd': 'path.to.callable', ...}`.
|
||||
- New `XYZGrid` contrib, adding x,y,z grid coordinates with in-game map and
|
||||
pathfinding. Controlled outside of the game via custom evennia launcher command.
|
||||
- `Script.delete` has new kwarg `stop_task=True`, that can be used to avoid
|
||||
infinite recursion when wanting to set up Script to delete-on-stop.
|
||||
- Command executions now done on copies to make sure `yield` don't cause crossovers. Add
|
||||
`Command.retain_instance` flag for reusing the same command instance.
|
||||
- The `typeclass` command will now correctly search the correct database-table for the target
|
||||
obj (avoids mistakenly assigning an AccountDB-typeclass to a Character etc).
|
||||
- Merged `script` and `scripts` commands into one, for both managing global- and
|
||||
on-object Scripts. Moved `CmdScripts` and `CmdObjects` to `commands/default/building.py`.
|
||||
- Keep GMCP function case if outputfunc starts with capital letter (so `cmd_name` -> `Cmd.Name`
|
||||
but `Cmd_nAmE` -> `Cmd.nAmE`). This helps e.g Mudlet's legacy `Client_GUI` implementation)
|
||||
- Prototypes now allow setting `prototype_parent` directly to a prototype-dict.
|
||||
This makes it easier when dynamically building in-module prototypes.
|
||||
- `RPSystem contrib` was expanded to support case, so /tall becomes 'tall man'
|
||||
while /Tall becomes 'Tall man'. One can turn this off if wanting the old style.
|
||||
- Change `EvTable` fixed-height rebalance algorithm to fill with empty lines at end of
|
||||
column instead of inserting rows based on cell-size (could be mistaken for a bug).
|
||||
- Split `return_appearance` hook with helper methods and have it use a template
|
||||
string in order to make it easier to override.
|
||||
- Add validation question to default account creation.
|
||||
- Add `LOCALECHO` client option to add server-side echo for clients that does
|
||||
not support this (useful for getting a complete log).
|
||||
- Make `@lazy_property` decorator create read/delete-protected properties. This is
|
||||
because it's used for handlers, and e.g. self.locks=[] is a common beginner mistake.
|
||||
- Add `$pron()` inlinefunc for pronoun parsing in actor-stance strings using
|
||||
`msg_contents`.
|
||||
- Update defauklt website to show Telnet/SSL/SSH connect info. Added new
|
||||
`SERVER_HOSTNAME` setting for use in the server:port stanza.
|
||||
- Changed all `at_before/after_*` hooks to `at_pre/post_*` for consistency
|
||||
across Evennia (the old names still work but are deprecated)
|
||||
- Change `settings.COMMAND_DEFAULT_ARG_REGEX` default from `None` to a regex meaning that
|
||||
a space or `/` must separate the cmdname and args. This better fits common expectations.
|
||||
- Add confirmation question to `ban`/`unban` commands.
|
||||
- Check new `teleport` and `teleport_here` lock-types in `teleport` command to optionally
|
||||
allow to limit teleportation of an object or to a specific destination.
|
||||
- Add `settings.MXP_ENABLED=True` and `settings.MXP_OUTGOING_ONLY=True` as sane defaults,
|
||||
to avoid known security issues with players entering MXP links.
|
||||
- Add browser name to webclient `CLIENT_NAME` in `session.protocol_flags`, e.g.
|
||||
`"Evennia webclient (websocket:firefox)"` or `"evennia webclient (ajax:chrome)"`.
|
||||
- `TagHandler.add/has(tag=...)` kwarg changed to `add/has(key=...)` for consistency
|
||||
with other handlers.
|
||||
- Make `DefaultScript.delete`, `DefaultChannel.delete` and `DefaultAccount.delete` return
|
||||
bool True/False if deletion was successful (like `DefaultObject.delete` before them)
|
||||
- `contrib.custom_gametime` days/weeks/months now always starts from 1 (to match
|
||||
the standard calendar form ... there is no month 0 every year after all).
|
||||
- `AttributeProperty`/`NAttributeProperty` to allow managing Attributes/NAttributes
|
||||
on typeclasses in the same way as Django fields.
|
||||
- Give build/system commands a `@name` to fall back to if the non-@ name is used
|
||||
by another command (like `open` and `@open`. If no duplicate, @ is optional.
|
||||
- Move legacy channel-management commands (`ccreate`, `addcom` etc) to a contrib
|
||||
since their work is now fully handled by the single `channel` command.
|
||||
- Expand `examine` command's code to much more extensible and modular. Show
|
||||
attribute categories and value types (when not strings).
|
||||
- `AttributeHandler.remove(key, return_exception=False, category=None, ...)` changed
|
||||
to `.remove(key, category=None, return_exception=False, ...)` for consistency.
|
||||
- New `command cooldown` contrib for making it easier to manage commands using
|
||||
dynamic cooldowns between uses (owllex)
|
||||
- Restructured `contrib/` folder, placing all contribs as separate packages under
|
||||
subfolders. All imports will need to be updated.
|
||||
- Made `MonitorHandler.add/remove` support `category` for monitoring Attributes
|
||||
with a category (before only key was used, ignoring category entirely).
|
||||
- Move `create_*` functions into db managers, leaving `utils.create` only being
|
||||
wrapper functions (consistent with `utils.search`). No change of api otherwise.
|
||||
- Add support for `$dbref()` and `$search` when assigning an Attribute value
|
||||
with the `set` command. This allows assigning real objects from in-game.
|
||||
- Add ability to examine `/script` and `/channel` entities with `examine` command.
|
||||
- Homogenize manager search methods to return querysets and not lists.
|
||||
- Restructure unit tests to always honor default settings; make new parents in
|
||||
on location for easy use in game dir.
|
||||
- The `Lunr` search engine used by help excludes common words; the settings-list
|
||||
`LUNR_STOP_WORD_FILTER_EXCEPTIONS` can be extended to make sure common names are included.
|
||||
- Add `.deserialize()` method to `_Saver*` structures to help completely
|
||||
decouple structures from database without needing separate import.
|
||||
- Add `run_in_main_thread` as a helper for those wanting to code server code
|
||||
from a web view.
|
||||
- Update `evennia.utils.logger` to use Twisted's new logging API. No change in Evennia API
|
||||
except more standard aliases logger.error/info/exception/debug etc can now be used.
|
||||
- Have `type/force` default to `update`-mode rather than `reset`mode and add more verbose
|
||||
warning when using reset mode.
|
||||
- Attribute storage support defaultdics (Hendher)
|
||||
- Add ObjectParent mixin to default game folder template as an easy, ready-made
|
||||
way to override features on all ObjectDB-inheriting objects easily.
|
||||
source location, mimicking behavior of `at_pre_move` hook - returning False will abort move.
|
||||
- Add `TagProperty`, `AliasProperty` and `PermissionProperty` to assign these
|
||||
data in a similar way to django fields.
|
||||
- New `at_pre_object_receive(obj, source_location)` method on Objects. Called on
|
||||
destination, mimicking behavior of `at_pre_move` hook - returning False will abort move.
|
||||
- New `at_pre_object_leave(obj, destination)` method on Objects. Called on
|
||||
- The db pickle-serializer now checks for methods `__serialize_dbobjs__` and `__deserialize_dbobjs__`
|
||||
to allow custom packing/unpacking of nested dbobjs, to allow storing in Attribute.
|
||||
- Optimizations to rpsystem contrib performance. Breaking change: `.get_sdesc()` will
|
||||
now return `None` instead of `.db.desc` if no sdesc is set; fallback in hook (inspectorCaracal)
|
||||
- Reworked text2html parser to avoid problems with stateful color tags (inspectorCaracal)
|
||||
- Simplified `EvMenu.options_formatter` hook to use `EvColumn` and f-strings (inspectorcaracal)
|
||||
- Allow `# CODE`, `# HEADER` etc as well as `#CODE`/`#HEADER` in batchcode
|
||||
files - this works better with black linting.
|
||||
- Added `move_type` str kwarg to `move_to()` calls, optionally identifying the type of
|
||||
move being done ('teleport', 'disembark', 'give' etc). (volund)
|
||||
- Made RPSystem contrib msg calls pass `pose` or `say` as msg-`type` for use in
|
||||
e.g. webclient pane filtering where desired. (volund)
|
||||
- Added `Account.uses_screenreader(session=None)` as a quick shortcut for
|
||||
finding if a user uses a screenreader (and adjust display accordingly).
|
||||
- Fixed bug in `cmdset.remove()` where a command could not be deleted by `key`,
|
||||
even though doc suggested one could (ChrisLR)
|
||||
- New contrib `name_generator` for building random real-world based or fantasy-names
|
||||
based on phonetic rules.
|
||||
- Enable proper serialization of dict subclasses in Attributes (aogier)
|
||||
- `object.search` fuzzy-matching now uses `icontains` instead of `istartswith`
|
||||
to better match how search works elsewhere (volund)
|
||||
- The `.at_traverse` hook now receives a `exit_obj` kwarg, linking back to the
|
||||
exit triggering the hook (volund)
|
||||
- Contrib `buffs` for managing temporary and permanent RPG status buffs effects (tegiminis)
|
||||
- New `at_server_init()` hook called before all other startup hooks for all
|
||||
startup modes. Used for more generic overriding (volund)
|
||||
- New `search` lock type used to completely hide an object from being found by
|
||||
the `DefaultObject.search` (`caller.search`) method. (CloudKeeper)
|
||||
- Change setting `MULTISESSION_MODE` to now only control sessions, not how many
|
||||
characters can be puppeted simultaneously. New settings now control that.
|
||||
- Add new setting `AUTO_CREATE_CHARACTER_WITH_ACCOUNT`, a boolean deciding if
|
||||
the new account should also get a matching character (legacy MUD style).
|
||||
- Add new setting `AUTO_PUPPET_ON_LOGIN`, boolean deciding if one should
|
||||
automatically puppet the last/available character on connection (legacy MUD style)
|
||||
- Add new setting `MAX_NR_SIMULTANEUS_PUPPETS` - how many puppets the account
|
||||
can run at the same time. Used to limit multi-playing.
|
||||
- Make setting `MAX_NR_CHARACTERS` interact better with the new settings above.
|
||||
- Allow `$search` funcparser func to search tags and to accept kwargs for more
|
||||
powerful searches passed into the regular search functions.
|
||||
- `spawner.spawn` and linked methods now has a kwarg `protfunc_raise_errors`
|
||||
(default True) to disable strict errors on malformed/not-found protfuncs
|
||||
- Improve search performance when having many DB-based prototypes via caching.
|
||||
- Remove the `return_parents` kwarg of `evennia.prototypes.spawner.spawn` since it
|
||||
was inefficient and unused.
|
||||
- Made all id fields BigAutoField for all databases. (owllex)
|
||||
- `EvForm` refactored. New `literals` mapping, for literal mappings into the
|
||||
main template (e.g. for single-character replacements).
|
||||
- `EvForm` `cells` kwarg now accepts `EvCells` with custom formatting options
|
||||
(mainly for custom align/valign). `EvCells` now makes use of `utils.justify`.
|
||||
- `utils.justify` now supports `align="a"` (absolute alignments. This keeps
|
||||
the given left indent but crops/fills to the width. Used in EvCells.
|
||||
- `EvTable` now supports passing `EvColumn`s as a list directly, (`EvTable(table=[colA,colB])`)
|
||||
- Add `tags=` search criterion to `DefaultObject.search`.
|
||||
- Add `AT_EXIT_TRAVERSE` signal, firing when an exit is traversed.
|
||||
- Add integration between Evennia and Discord channels (PR by Inspector Cararacal)
|
||||
- Support for using a Godot-powered client with Evennia (PR by ChrisLR)
|
||||
- Added German translation (patch by Zhuraj)
|
||||
|
||||
## Evennia 0.9.5
|
||||
|
||||
> 2019-2020
|
||||
> Released 2020-11-14.
|
||||
> Transitional release, including new doc system.
|
||||
|
||||
Backported from develop: Python 3.8, 3.9 support. Django 3.2+ support, Twisted 21+ support.
|
||||
|
||||
- `is_typeclass(obj (Object), exact (bool))` now defaults to exact=False
|
||||
- `py` command now reroutes stdout to output results in-game client. `py`
|
||||
without arguments starts a full interactive Python console.
|
||||
- Webclient default to a single input pane instead of two. Now defaults to no help-popup.
|
||||
- Webclient fix of prompt display
|
||||
- Webclient multimedia support for relaying images, video and sounds via
|
||||
`.msg(image=URL)`, `.msg(video=URL)`
|
||||
and `.msg(audio=URL)`
|
||||
- Add Spanish translation (fermuch)
|
||||
- Expand `GLOBAL_SCRIPTS` container to always start scripts and to include all
|
||||
global scripts regardless of how they were created.
|
||||
- Change settings to always use lists instead of tuples, to make mutable
|
||||
settings easier to add to. (#1912)
|
||||
- Make new `CHANNEL_MUDINFO` setting for specifying the mudinfo channel
|
||||
- Make `CHANNEL_CONNECTINFO` take full channel definition
|
||||
- Make `DEFAULT_CHANNELS` list auto-create channels missing at reload
|
||||
- Webclient `ANSI->HTML` parser updated. Webclient line width changed from 1.6em to 1.1em
|
||||
to better make ANSI graphics look the same as for third-party clients
|
||||
- `AttributeHandler.get(return_list=True)` will return `[]` if there are no
|
||||
Attributes instead of `[None]`.
|
||||
- Remove `pillow` requirement (install especially if using imagefield)
|
||||
- Add Simplified Korean translation (aceamro)
|
||||
- Show warning on `start -l` if settings contains values unsafe for production.
|
||||
- Make code auto-formatted with Black.
|
||||
- Make default `set` command able to edit nested structures (PR by Aaron McMillan)
|
||||
- Allow running Evennia test suite from core repo with `make test`.
|
||||
- Return `store_key` from `TickerHandler.add` and add `store_key` as a kwarg to
|
||||
the `TickerHandler.remove` method. This makes it easier to manage tickers.
|
||||
- EvMore auto-justify now defaults to False since this works better with all types
|
||||
of texts (such as tables). New `justify` bool. Old `justify_kwargs` remains
|
||||
but is now only used to pass extra kwargs into the justify function.
|
||||
- EvMore `text` argument can now also be a list or a queryset. Querysets will be
|
||||
sliced to only return the required data per page.
|
||||
- Improve performance of `find` and `objects` commands on large data sets (strikaco)
|
||||
- New `CHANNEL_HANDLER_CLASS` setting allows for replacing the ChannelHandler entirely.
|
||||
- Made `py` interactive mode support regular quit() and more verbose.
|
||||
- Made `Account.options.get` accept `default=None` kwarg to mimic other uses of get. Set
|
||||
the new `raise_exception` boolean if ranting to raise KeyError on a missing key.
|
||||
- Moved behavior of unmodified `Command` and `MuxCommand` `.func()` to new
|
||||
`.get_command_info()` method for easier overloading and access. (Volund)
|
||||
- Removed unused `CYCLE_LOGFILES` setting. Added `SERVER_LOG_DAY_ROTATION`
|
||||
and `SERVER_LOG_MAX_SIZE` (and equivalent for PORTAL) to control log rotation.
|
||||
- Addded `inside_rec` lockfunc - if room is locked, the normal `inside()` lockfunc will
|
||||
fail e.g. for your inventory objs (since their loc is you), whereas this will pass.
|
||||
- RPSystem contrib's CmdRecog will now list all recogs if no arg is given. Also multiple
|
||||
bugfixes.
|
||||
- Remove `dummy@example.com` as a default account email when unset, a string is no longer
|
||||
required by Django.
|
||||
- Fixes to `spawn`, make updating an existing prototype/object work better. Add `/raw` switch
|
||||
to `spawn` command to extract the raw prototype dict for manual editing.
|
||||
- `list_to_string` is now `iter_to_string` (but old name still works as legacy alias). It will
|
||||
now accept any input, including generators and single values.
|
||||
- EvTable should now correctly handle columns with wider asian-characters in them.
|
||||
- Update Twisted requirement to >=2.3.0 to close security vulnerability
|
||||
- Add `$random` inlinefunc, supports minval,maxval arguments that can be ints and floats.
|
||||
- Add `evennia.utils.inlinefuncs.raw(<str>)` as a helper to escape inlinefuncs in a string.
|
||||
- Make CmdGet/Drop/Give give proper error if `obj.move_to` returns `False`.
|
||||
- Make `Object/Room/Exit.create`'s `account` argument optional. If not given, will set perms
|
||||
to that of the object itself (along with normal Admin/Dev permission).
|
||||
- Make `INLINEFUNC_STACK_MAXSIZE` default visible in `settings_default.py`.
|
||||
- Change how `ic` finds puppets; non-priveleged users will use `_playable_characters` list as
|
||||
candidates, Builders+ will use list, local search and only global search if no match found.
|
||||
- Make `cmd.at_post_cmd()` always run after `cmd.func()`, even when the latter uses delays
|
||||
with yield.
|
||||
- `EvMore` support for db queries and django paginators as well as easier to override for custom
|
||||
pagination (e.g. to create EvTables for every page instead of splittine one table)
|
||||
- Using `EvMore pagination`, dramatically improves performance of `spawn/list` and `scripts` listings
|
||||
(100x speed increase for displaying 1000+ prototypes/scripts).
|
||||
- `EvMenu` now uses the more logically named `.ndb._evmenu` instead of `.ndb._menutree` to store itself.
|
||||
Both still work for backward compatibility, but `_menutree` is deprecated.
|
||||
- `EvMenu.msg(txt)` added as a central place to send text to the user, makes it easier to override.
|
||||
Default `EvMenu.msg` sends with OOB type="menu" for use with OOB and webclient pane-redirects.
|
||||
- New EvMenu templating system for quickly building simpler EvMenus without as much code.
|
||||
- Add `Command.client_height()` method to match existing `.client_width` (stricako)
|
||||
- Include more Web-client info in `session.protocol_flags`.
|
||||
- Fixes in multi-match situations - don't allow finding/listing multimatches for 3-box when
|
||||
only two boxes in location.
|
||||
- Fix for TaskHandler with proper deferred returns/ability to cancel etc (PR by davewiththenicehat)
|
||||
- Add `PermissionHandler.check` method for straight string perm-checks without needing lockstrings.
|
||||
- Add `evennia.utils.utils.strip_unsafe_input` for removing html/newlines/tags from user input. The
|
||||
`INPUT_CLEANUP_BYPASS_PERMISSIONS` is a list of perms that bypass this safety stripping.
|
||||
- Make default `set` and `examine` commands aware of Attribute categories.
|
||||
|
||||
## Evennia 0.9
|
||||
|
||||
> 2018-2019
|
||||
> Released Oct 2019
|
||||
|
||||
### Distribution
|
||||
|
||||
- New requirement: Python 3.7 (py2.7 support removed)
|
||||
- Django 2.1
|
||||
- Twisted 19.2.1
|
||||
- Autobahn websockets (removed old tmwx)
|
||||
- Docker image updated
|
||||
|
||||
### Commands
|
||||
|
||||
- Remove `@`-prefix from all default commands (prefixes still work, optional)
|
||||
- Removed default `@delaccount` command, incorporating as `@account/delete` instead. Added confirmation
|
||||
question.
|
||||
- Add new `@force` command to have another object perform a command.
|
||||
- Add the Portal uptime to the `@time` command.
|
||||
- Make the `@link` command first make a local search before a global search.
|
||||
- Have the default Unloggedin-look command look for optional `connection_screen()` callable in
|
||||
`mygame/server/conf/connection_screen.py`. This allows for more flexible welcome screens
|
||||
that are calculated on the fly.
|
||||
- `@py` command now defaults to escaping html tags in its output when viewing in the webclient.
|
||||
Use new `/clientraw` switch to get old behavior (issue #1369).
|
||||
- Shorter and more informative, dynamic, listing of on-command vars if not
|
||||
setting func() in child command class.
|
||||
- New Command helper methods
|
||||
- `.client_width()` returns client width of the session running the command.
|
||||
- `.styled_table(*args, **kwargs)` returns a formatted evtable styled by user's options
|
||||
- `.style_header(*args, **kwargs)` creates styled header entry
|
||||
- `.style_separator(*args, **kwargs)` " separator
|
||||
- `.style_footer(*args, **kwargs)` " footer
|
||||
|
||||
### Web
|
||||
|
||||
- Change webclient from old txws version to use more supported/feature-rich Autobahn websocket library
|
||||
|
||||
#### Evennia game index
|
||||
|
||||
- Made Evennia game index client a part of core - now configured from settings file (old configs
|
||||
need to be moved)
|
||||
- The `evennia connections` command starts a wizard that helps you connect your game to the game index.
|
||||
- The game index now accepts games with no public telnet/webclient info (for early prototypes).
|
||||
|
||||
#### New golden-layout based Webclient UI (@friarzen)
|
||||
- Features
|
||||
- Much slicker behavior and more professional look
|
||||
- Allows tabbing as well as click and drag of panes in any grid position
|
||||
- Renaming tabs, assignments of data tags and output types are simple per-pane menus now
|
||||
- Any number of input panes, with separate histories
|
||||
- Button UI (disabled in JS by default)
|
||||
|
||||
#### Web/Django standard initiative (@strikaco)
|
||||
- Features
|
||||
- Adds a series of web-based forms and generic class-based views
|
||||
- Accounts
|
||||
- Register - Enhances registration; allows optional collection of email address
|
||||
- Form - Adds a generic Django form for creating Accounts from the web
|
||||
- Characters
|
||||
- Create - Authenticated users can create new characters from the website (requires associated form)
|
||||
- Detail - Authenticated and authorized users can view select details about characters
|
||||
- List - Authenticated and authorized users can browse a list of all characters
|
||||
- Manage - Authenticated users can edit or delete owned characters from the web
|
||||
- Form - Adds a generic Django form for creating characters from the web
|
||||
- Channels
|
||||
- Detail - Authorized users can view channel logs from the web
|
||||
- List - Authorized users can browse a list of all channels
|
||||
- Help Entries
|
||||
- Detail - Authorized users can view help entries from the web
|
||||
- List - Authorized users can browse a list of all help entries from the web
|
||||
- Navbar changes
|
||||
- Characters - Link to character list
|
||||
- Channels - Link to channel list
|
||||
- Help - Link to help entry list
|
||||
- Puppeting
|
||||
- Users can puppet their own characters within the context of the website
|
||||
- Dropdown
|
||||
- Link to create characters
|
||||
- Link to manage characters
|
||||
- Link to quick-select puppets
|
||||
- Link to password change workflow
|
||||
- Functions
|
||||
- Updates Bootstrap to v4 stable
|
||||
- Enables use of Django Messages framework to communicate with users in browser
|
||||
- Implements webclient/website `_shared_login` functionality as Django middleware
|
||||
- 'account' and 'puppet' are added to all request contexts for authenticated users
|
||||
- Adds unit tests for all web views
|
||||
- Cosmetic
|
||||
- Prettifies Django 'forgot password' workflow (requires SMTP to actually function)
|
||||
- Prettifies Django 'change password' workflow
|
||||
- Bugfixes
|
||||
- Fixes bug on login page where error messages were not being displayed
|
||||
- Remove strvalue field from admin; it made no sense to have here, being an optimization field
|
||||
for internal use.
|
||||
|
||||
### Prototypes
|
||||
|
||||
- `evennia.prototypes.save_prototype` now takes the prototype as a normal
|
||||
argument (`prototype`) instead of having to give it as `**prototype`.
|
||||
- `evennia.prototypes.search_prototype` has a new kwarg `require_single=False` that
|
||||
raises a KeyError exception if query gave 0 or >1 results.
|
||||
- `evennia.prototypes.spawner` can now spawn by passing a `prototype_key`
|
||||
|
||||
### Typeclasses
|
||||
|
||||
- Add new methods on all typeclasses, useful specifically for object handling from the website/admin:
|
||||
+ `web_get_admin_url()`: Returns the path to the object detail page in the Admin backend.
|
||||
+ `web_get_create_url()`: Returns the path to the typeclass' creation page on the website, if implemented.
|
||||
+ `web_get_absolute_url()`: Returns the path to the object's detail page on the website, if implemented.
|
||||
+ `web_get_update_url()`: Returns the path to the object's update page on the website, if implemented.
|
||||
+ `web_get_delete_url()`: Returns the path to the object's delete page on the website, if implemented.
|
||||
- All typeclasses have new helper class method `create`, which encompasses useful functionality
|
||||
that used to be embedded for example in the respective `@create` or `@connect` commands.
|
||||
- DefaultAccount now has new class methods implementing many things that used to be in unloggedin
|
||||
commands (these can now be customized on the class instead):
|
||||
+ `is_banned()`: Checks if a given username or IP is banned.
|
||||
+ `get_username_validators`: Return list of validators for username validation (see
|
||||
`settings.AUTH_USERNAME_VALIDATORS`)
|
||||
+ `authenticate`: Method to check given username/password.
|
||||
+ `normalize_username`: Normalizes names so (for Unicode environments) users cannot mimic existing usernames by replacing select characters with visually-similar Unicode chars.
|
||||
+ `validate_username`: Mechanism for validating a username based on predefined Django validators.
|
||||
+ `validate_password`: Mechanism for validating a password based on predefined Django validators.
|
||||
+ `set_password`: Apply password to account, using validation checks.
|
||||
- `AttributeHandler.remove` and `TagHandler.remove` can now be used to delete by-category. If neither
|
||||
key nor category is given, they now work the same as .clear().
|
||||
|
||||
### Protocols
|
||||
|
||||
- Support for `Grapevine` MUD-chat network ("channels" supported)
|
||||
|
||||
### Server
|
||||
|
||||
- Convert ServerConf model to store its values as a Picklefield (same as
|
||||
Attributes) instead of using a custom solution.
|
||||
- OOB: Add support for MSDP LIST, REPORT, UNREPORT commands (re-mapped to `msdp_list`,
|
||||
`msdp_report`, `msdp_unreport`, inlinefuncs)
|
||||
- Added `evennia.ANSIString` to flat API.
|
||||
- Server/Portal log files now cycle to names on the form `server_.log_19_03_08_` instead of `server.log___19.3.8`, retaining
|
||||
unix file sorting order.
|
||||
- Django signals fire for important events: Puppet/Unpuppet, Object create/rename, Login,
|
||||
Logout, Login fail Disconnect, Account create/rename
|
||||
|
||||
### Settings
|
||||
|
||||
- `GLOBAL_SCRIPTS` - dict defining typeclasses of global scripts to store on the new
|
||||
`evennia.GLOBAL_SCRIPTS` container. These will auto-start when Evennia start and will always
|
||||
exist.
|
||||
- `OPTIONS_ACCOUNTS_DEFAULT` - option dict with option defaults and Option classes
|
||||
- `OPTION_CLASS_MODULES` - classes representing an on-Account Option, on special form
|
||||
- `VALIDATOR_FUNC_MODULES` - (general) text validator functions, for verifying an input
|
||||
is on a specific form.
|
||||
|
||||
### Utils
|
||||
|
||||
- `evennia` launcher now fully handles all django-admin commands, like running tests in parallel.
|
||||
- `evennia.utils.create.account` now also takes `tags` and `attrs` keywords.
|
||||
- `evennia.utils.interactive` decorator can now allow you to use yield(secs) to pause operation
|
||||
in any function, not just in Command.func. Likewise, response = yield(question) will work
|
||||
if the decorated function has an argument or kwarg `caller`.
|
||||
- Added many more unit tests.
|
||||
- Swap argument order of `evennia.set_trace` to `set_trace(term_size=(140, 40), debugger='auto')`
|
||||
since the size is more likely to be changed on the command line.
|
||||
- `utils.to_str(text, session=None)` now acts as the old `utils.to_unicode` (which was removed).
|
||||
This converts to the str() type (not to a byte-string as in Evennia 0.8), trying different
|
||||
encodings. This function will also force-convert any object passed to it into a string (so
|
||||
`force_string` flag was removed and assumed always set).
|
||||
- `utils.to_bytes(text, session=None)` replaces the old `utils.to_str()` functionality and converts
|
||||
str to bytes.
|
||||
- `evennia.MONITOR_HANDLER.all` now takes keyword argument `obj` to only retrieve monitors from that specific
|
||||
Object (rather than all monitors in the entire handler).
|
||||
- Support adding `\f` in command doc strings to force where EvMore puts page breaks.
|
||||
- Validation Functions now added with standard API to homogenize user input validation.
|
||||
- Option Classes added to make storing user-options easier and smoother.
|
||||
- `evennia.VALIDATOR_CONTAINER` and `evennia.OPTION_CONTAINER` added to load these.
|
||||
|
||||
### Contribs
|
||||
|
||||
- Evscaperoom - a full puzzle engine for making multiplayer escape rooms in Evennia. Used to make
|
||||
the entry for the MUD-Coder's Guild's 2019 Game Jam with the theme "One Room", where it ranked #1.
|
||||
- Evennia game-index client no longer a contrib - moved into server core and configured with new
|
||||
setting `GAME_INDEX_ENABLED`.
|
||||
- The `extended_room` contrib saw some backwards-incompatible refactoring:
|
||||
+ All commands now begin with `CmdExtendedRoom`. So before it was `CmdExtendedLook`, now
|
||||
it's `CmdExtendedRoomLook` etc.
|
||||
+ The `detail` command was broken out of the `desc` command and is now a new, stand-alone command
|
||||
`CmdExtendedRoomDetail`. This was done to make things easier to extend and to mimic how the detail
|
||||
command works in the tutorial-world.
|
||||
+ The `detail` command now also supports deleting details (like the tutorial-world version).
|
||||
+ The new `ExtendedRoomCmdSet` includes all the extended-room commands and is now the recommended way
|
||||
to install the extended-room contrib.
|
||||
- Reworked `menu_login` contrib to use latest EvMenu standards. Now also supports guest logins.
|
||||
- Mail contrib was refactored to have optional Command classes `CmdMail` for OOC+IC mail (added
|
||||
to the CharacterCmdSet and `CmdMailCharacter` for IC-only mailing between chars (added to CharacterCmdSet)
|
||||
|
||||
### Translations
|
||||
|
||||
- Simplified chinese, courtesy of user MaxAlex.
|
||||
|
||||
|
||||
## Evennia 0.8
|
||||
|
||||
> 2017-2018
|
||||
> Released Nov 2018
|
||||
|
||||
### Requirements
|
||||
|
||||
- Up requirements to Django 1.11.x, Twisted 18 and pillow 5.2.0
|
||||
- Add `inflect` dependency for automatic pluralization of object names.
|
||||
|
||||
### Server/Portal
|
||||
|
||||
- Removed `evennia_runner`, completely refactor `evennia_launcher.py` (the 'evennia' program)
|
||||
with different functionality).
|
||||
- Both Portal/Server are now stand-alone processes (easy to run as daemon)
|
||||
- Made Portal the AMP Server for starting/restarting the Server (the AMP client)
|
||||
- Dynamic logging now happens using `evennia -l` rather than by interactive mode.
|
||||
- Made AMP secure against erroneous HTTP requests on the wrong port (return error messages).
|
||||
- The `evennia istart` option will start/switch the Server in foreground (interactive) mode, where it logs
|
||||
to terminal and can be stopped with Ctrl-C. Using `evennia reload`, or reloading in-game, will
|
||||
return Server to normal daemon operation.
|
||||
- For validating passwords, use safe Django password-validation backend instead of custom Evennia one.
|
||||
- Alias `evennia restart` to mean the same as `evennia reload`.
|
||||
|
||||
### Prototype changes
|
||||
|
||||
- New OLC started from `olc` command for loading/saving/manipulating prototypes in a menu.
|
||||
- Moved evennia/utils/spawner.py into the new evennia/prototypes/ along with all new
|
||||
functionality around prototypes.
|
||||
- A new form of prototype - database-stored prototypes, editable from in-game, was added. The old,
|
||||
module-created prototypes remain as read-only prototypes.
|
||||
- All prototypes must have a key `prototype_key` identifying the prototype in listings. This is
|
||||
checked to be server-unique. Prototypes created in a module will use the global variable name they
|
||||
are assigned to if no `prototype_key` is given.
|
||||
- Prototype field `prototype` was renamed to `prototype_parent` to avoid mixing terms.
|
||||
- All prototypes must either have `typeclass` or `prototype_parent` defined. If using
|
||||
`prototype_parent`, `typeclass` must be defined somewhere in the inheritance chain. This is a
|
||||
change from Evennia 0.7 which allowed 'mixin' prototypes without `typeclass`/`prototype_key`. To
|
||||
make a mixin now, give it a default typeclass, like `evennia.objects.objects.DefaultObject` and just
|
||||
override in the child as needed.
|
||||
- Spawning an object using a prototype will automatically assign a new tag to it, named the same as
|
||||
the `prototype_key` and with the category `from_prototype`.
|
||||
- The spawn command was extended to accept a full prototype on one line.
|
||||
- The spawn command got the /save switch to save the defined prototype and its key
|
||||
- The command spawn/menu will now start an OLC (OnLine Creation) menu to load/save/edit/spawn prototypes.
|
||||
|
||||
### EvMenu
|
||||
|
||||
- Added `EvMenu.helptext_formatter(helptext)` to allow custom formatting of per-node help.
|
||||
- Added `evennia.utils.evmenu.list_node` decorator for turning an EvMenu node into a multi-page listing.
|
||||
- A `goto` option callable returning None (rather than the name of the next node) will now rerun the
|
||||
current node instead of failing.
|
||||
- Better error handling of in-node syntax errors.
|
||||
- Improve dedent of default text/helptext formatter. Right-strip whitespace.
|
||||
- Add `debug` option when creating menu - this turns off persistence and makes the `menudebug`
|
||||
command available for examining the current menu state.
|
||||
|
||||
|
||||
### Webclient
|
||||
|
||||
- Webclient now uses a plugin system to inject new components from the html file.
|
||||
- Split-windows - divide input field into any number of horizontal/vertical panes and
|
||||
assign different types of server messages to them.
|
||||
- Lots of cleanup and bug fixes.
|
||||
- Hot buttons plugin (friarzen) (disabled by default).
|
||||
|
||||
### Locks
|
||||
|
||||
- New function `evennia.locks.lockhandler.check_lockstring`. This allows for checking an object
|
||||
against an arbitrary lockstring without needing the lock to be stored on an object first.
|
||||
- New function `evennia.locks.lockhandler.validate_lockstring` allows for stand-alone validation
|
||||
of a lockstring.
|
||||
- New function `evennia.locks.lockhandler.get_all_lockfuncs` gives a dict {"name": lockfunc} for
|
||||
all available lock funcs. This is useful for dynamic listings.
|
||||
|
||||
|
||||
### Utils
|
||||
|
||||
- Added new `columnize` function for easily splitting text into multiple columns. At this point it
|
||||
is not working too well with ansi-colored text however.
|
||||
- Extend the `dedent` function with a new `baseline_index` kwarg. This allows to force all lines to
|
||||
the indentation given by the given line regardless of if other lines were already a 0 indentation.
|
||||
This removes a problem with the original `textwrap.dedent` which will only dedent to the least
|
||||
indented part of a text.
|
||||
- Added `exit_cmd` to EvMore pager, to allow for calling a command (e.g. 'look') when leaving the pager.
|
||||
- `get_all_typeclasses` will return dict `{"path": typeclass, ...}` for all typeclasses available
|
||||
in the system. This is used by the new `@typeclass/list` subcommand (useful for builders etc).
|
||||
- `evennia.utils.dbserialize.deserialize(obj)` is a new helper function to *completely* disconnect
|
||||
a mutable recovered from an Attribute from the database. This will convert all nested `_Saver*`
|
||||
classes to their plain-Python counterparts.
|
||||
|
||||
### General
|
||||
|
||||
- Start structuring the `CHANGELOG` to list features in more detail.
|
||||
- Docker image `evennia/evennia:develop` is now auto-built, tracking the develop branch.
|
||||
- Inflection and grouping of multiple objects in default room (an box, three boxes)
|
||||
- `evennia.set_trace()` is now a shortcut for launching pdb/pudb on a line in the Evennia event loop.
|
||||
- Removed the enforcing of `MAX_NR_CHARACTERS=1` for `MULTISESSION_MODE` `0` and `1` by default.
|
||||
- Add `evennia.utils.logger.log_sec` for logging security-related messages (marked SS in log).
|
||||
|
||||
### Contribs
|
||||
|
||||
- `Auditing` (Johnny): Log and filter server input/output for security purposes
|
||||
- `Build Menu` (vincent-lg): New @edit command to edit object properties in a menu.
|
||||
- `Field Fill` (Tim Ashley Jenkins): Wraps EvMenu for creating submittable forms.
|
||||
- `Health Bar` (Tim Ashley Jenkins): Easily create colorful bars/meters.
|
||||
- `Tree select` (Fluttersprite): Wrap EvMenu to create a common type of menu from a string.
|
||||
- `Turnbattle suite` (Tim Ashley Jenkins)- the old `turnbattle.py` was moved into its own
|
||||
`turnbattle/` package and reworked with many different flavors of combat systems:
|
||||
- `tb_basic` - The basic turnbattle system, with initiative/turn order attack/defense/damage.
|
||||
- `tb_equip` - Adds weapon and armor, wielding, accuracy modifiers.
|
||||
- `tb_items` - Extends `tb_equip` with item use with conditions/status effects.
|
||||
- `tb_magic` - Extends `tb_equip` with spellcasting.
|
||||
- `tb_range` - Adds system for abstract positioning and movement.
|
||||
- The `extended_room` contrib saw some backwards-incompatible refactoring:
|
||||
- All commands now begin with `CmdExtendedRoom`. So before it was `CmdExtendedLook`, now
|
||||
it's `CmdExtendedRoomLook` etc.
|
||||
- The `detail` command was broken out of the `desc` command and is now a new, stand-alone command
|
||||
`CmdExtendedRoomDetail`. This was done to make things easier to extend and to mimic how the detail
|
||||
command works in the tutorial-world.
|
||||
- The `detail` command now also supports deleting details (like the tutorial-world version).
|
||||
- The new `ExtendedRoomCmdSet` includes all the extended-room commands and is now the recommended way
|
||||
to install the extended-room contrib.
|
||||
- Updates and some cleanup of existing contribs.
|
||||
|
||||
|
||||
### Internationalization
|
||||
|
||||
- Polish translation by user ogotai
|
||||
|
||||
# Overview-Changelogs
|
||||
|
||||
> These are changelogs from a time before we used formal version numbers.
|
||||
|
||||
## Sept 2017:
|
||||
Release of Evennia 0.7; upgrade to Django 1.11, change 'Player' to
|
||||
'Account', rework the website template and a slew of other updates.
|
||||
Info on what changed and how to migrate is found here:
|
||||
https://groups.google.com/forum/#!msg/evennia/0JYYNGY-NfE/cDFaIwmPBAAJ
|
||||
|
||||
## Feb 2017:
|
||||
New devel branch created, to lead up to Evennia 0.7.
|
||||
|
||||
## Dec 2016:
|
||||
Lots of bugfixes and considerable uptick in contributors. Unittest coverage
|
||||
and PEP8 adoption and refactoring.
|
||||
|
||||
## May 2016:
|
||||
Evennia 0.6 with completely reworked Out-of-band system, making
|
||||
the message path completely flexible and built around input/outputfuncs.
|
||||
A completely new webclient, split into the evennia.js library and a
|
||||
gui library, making it easier to customize.
|
||||
|
||||
## Feb 2016:
|
||||
Added the new EvMenu and EvMore utilities, updated EvEdit and cleaned up
|
||||
a lot of the batchcommand functionality. Started work on new Devel branch.
|
||||
|
||||
## Sept 2015:
|
||||
Evennia 0.5. Merged devel branch, full library format implemented.
|
||||
|
||||
## Feb 2015:
|
||||
Development currently in devel/ branch. Moved typeclasses to use
|
||||
django's proxy functionality. Changed the Evennia folder layout to a
|
||||
library format with a stand-alone launcher, in preparation for making
|
||||
an 'evennia' pypy package and using versioning. The version we will
|
||||
merge with will likely be 0.5. There is also work with an expanded
|
||||
testing structure and the use of threading for saves. We also now
|
||||
use Travis for automatic build checking.
|
||||
|
||||
## Sept 2014:
|
||||
Updated to Django 1.7+ which means South dependency was dropped and
|
||||
minimum Python version upped to 2.7. MULTISESSION_MODE=3 was added
|
||||
and the web customization system was overhauled using the latest
|
||||
functionality of django. Otherwise, mostly bug-fixes and
|
||||
implementation of various smaller feature requests as we got used
|
||||
to github. Many new users have appeared.
|
||||
|
||||
## Jan 2014:
|
||||
Moved Evennia project from Google Code to github.com/evennia/evennia.
|
||||
|
||||
## Nov 2013:
|
||||
Moved the internal webserver into the Server and added support for
|
||||
out-of-band protocols (MSDP initially). This large development push
|
||||
also meant fixes and cleanups of the way attributes were handled.
|
||||
Tags were added, along with proper handlers for permissions, nicks
|
||||
and aliases.
|
||||
|
||||
## May 2013:
|
||||
Made players able to control more than one Character at the same
|
||||
time, through the MULTISESSION_MODE=2 addition. This lead to a lot
|
||||
of internal changes for the server.
|
||||
|
||||
## Oct 2012:
|
||||
Changed Evennia from the Modified Artistic 1.0 license to the more
|
||||
standard and permissive BSD license. Lots of updates and bug fixes as
|
||||
more people start to use it in new ways. Lots of new caching and
|
||||
speed-ups.
|
||||
|
||||
## March 2012:
|
||||
Evennia's API has changed and simplified slightly in that the
|
||||
base-modules where removed from game/gamesrc. Instead admins are
|
||||
encouraged to explicitly create new modules under game/gamesrc/ when
|
||||
they want to implement their game - gamesrc/ is empty by default
|
||||
except for the example folders that contain template files to use for
|
||||
this purpose. We also added the ev.py file, implementing a new, flat
|
||||
API. Work is ongoing to add support for mud-specific telnet
|
||||
extensions, notably the MSDP and GMCP out-of-band extensions. On the
|
||||
community side, evennia's dev blog was started and linked on planet
|
||||
Mud-dev aggregator.
|
||||
|
||||
## Nov 2011:
|
||||
After creating several different proof-of-concept game systems (in
|
||||
contrib and privately) as well testing lots of things to make sure the
|
||||
implementation is basically sound, we are declaring Evennia out of
|
||||
Alpha. This can mean as much or as little as you want, admittedly -
|
||||
development is still heavy but the issue list is at an all-time low
|
||||
and the server is slowly stabilizing as people try different things
|
||||
with it. So Beta it is!
|
||||
|
||||
## Aug 2011:
|
||||
Split Evennia into two processes: Portal and Server. After a lot of
|
||||
work trying to get in-memory code-reloading to work, it's clear this
|
||||
is not Python's forte - it's impossible to catch all exceptions,
|
||||
especially in asynchronous code like this. Trying to do so results in
|
||||
hackish, flakey and unstable code. With the Portal-Server split, the
|
||||
Server can simply be rebooted while players connected to the Portal
|
||||
remain connected. The two communicates over twisted's AMP protocol.
|
||||
|
||||
## May 2011:
|
||||
The new version of Evennia, originally hitting trunk in Aug2010, is
|
||||
maturing. All commands from the pre-Aug version, including IRC/IMC2
|
||||
support works again. An ajax web-client was added earlier in the year,
|
||||
including moving Evennia to be its own webserver (no more need for
|
||||
Apache or django-testserver). Contrib-folder added.
|
||||
|
||||
## Aug 2010:
|
||||
Evennia-griatch-branch is ready for merging with trunk. This marks a
|
||||
rather big change in the inner workings of the server, such as the
|
||||
introduction of TypeClasses and Scripts (as compared to the old
|
||||
ScriptParents and Events) but should hopefully bring everything
|
||||
together into one consistent package as code development continues.
|
||||
|
||||
## May 2010:
|
||||
Evennia is currently being heavily revised and cleaned from
|
||||
the years of gradual piecemeal development. It is thus in a very
|
||||
'Alpha' stage at the moment. This means that old code snippets
|
||||
will not be backwards compatabile. Changes touch almost all
|
||||
parts of Evennia's innards, from the way Objects are handled
|
||||
to Events, Commands and Permissions.
|
||||
|
||||
## April 2010:
|
||||
Griatch takes over Maintainership of the Evennia project from
|
||||
the original creator Greg Taylor.
|
||||
|
||||
# Older
|
||||
|
||||
Earlier revisions, with previous maintainer, used SVN on Google Code
|
||||
and have no changelogs.
|
||||
|
||||
First commit (Evennia's birthday) was November 20, 2006.
|
||||
33
docs/1.x/_sources/Coding/Coding-Overview.md.txt
Normal file
33
docs/1.x/_sources/Coding/Coding-Overview.md.txt
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
# Coding and development help
|
||||
|
||||
This documentation aims to help you set up a sane development environment to
|
||||
make your game, also if you never coded before.
|
||||
|
||||
See also the [Beginner Tutorial](../Howtos/Beginner-Tutorial/Beginner-Tutorial-Overview.md).
|
||||
|
||||
```{toctree}
|
||||
:maxdepth: 2
|
||||
|
||||
Evennia-Code-Style.md
|
||||
Default-Command-Syntax.md
|
||||
Version-Control.md
|
||||
Debugging.md
|
||||
Unit-Testing.md
|
||||
Profiling.md
|
||||
Continuous-Integration.md
|
||||
Setting-up-PyCharm.md
|
||||
```
|
||||
|
||||
## Evennia Changelog
|
||||
|
||||
```{toctree}
|
||||
:maxdepth: 2
|
||||
|
||||
Changelog.md
|
||||
```
|
||||
|
||||
|
||||
```{toctree}
|
||||
:hidden:
|
||||
Release-Notes-1.0
|
||||
```
|
||||
198
docs/1.x/_sources/Coding/Continuous-Integration-TeamCity.md.txt
Normal file
198
docs/1.x/_sources/Coding/Continuous-Integration-TeamCity.md.txt
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
# Continuous Integration - TeamCity (linux)
|
||||
|
||||
This sets up a TeamCity build integration environment on Linux.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Follow [TeamCity](https://www.jetbrains.com/teamcity/) 's in-depth
|
||||
[Setup Guide](https://confluence.jetbrains.com/display/TCD8/Installing+and+Configuring+the+TeamCity+Server).
|
||||
- You need to use [Version Control](./Version-Control.md).
|
||||
|
||||
After meeting the preparation steps for your specific environment, log on to your teamcity interface
|
||||
at `http://<your server>:8111/`.
|
||||
|
||||
Create a new project named "Evennia" and in it construct a new template called `continuous-integration`.
|
||||
|
||||
## A Quick Overview
|
||||
|
||||
_Templates_ are fancy objects in TeamCity that allow an administrator to define build steps that are
|
||||
shared between one or more build projects. Assigning a VCS Root (Source Control) is unnecessary at
|
||||
this stage, primarily you'll be worrying about the build steps and your default parameters (both
|
||||
visible on the tabs to the left.)
|
||||
|
||||
## Template Setup
|
||||
|
||||
In this template, you'll be outlining the steps necessary to build your specific game. (A number of
|
||||
sample scripts are provided under this section below!) Click Build Steps and prepare your general
|
||||
flow. For this example, we will be doing a few basic example steps:
|
||||
|
||||
* Transforming the Settings.py file - We do this to update ports or other information that make your production
|
||||
environment unique from your development environment.
|
||||
* Making migrations and migrating the game database.
|
||||
* Publishing the game files.
|
||||
* Reloading the server.
|
||||
|
||||
For each step we'll being use the "Command Line Runner" (a fancy name for a shell script executor).
|
||||
|
||||
Create a build step with the name: "Transform Configuration" and add the script:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# Replaces the game configuration with one
|
||||
# appropriate for this deployment.
|
||||
|
||||
CONFIG="%system.teamcity.build.checkoutDir%/server/conf/settings.py"
|
||||
MYCONF="%system.teamcity.build.checkoutDir%/server/conf/my.cnf"
|
||||
|
||||
sed -e 's/TELNET_PORTS = [4000]/TELNET_PORTS = [%game.ports%]/g' "$CONFIG" > "$CONFIG".tmp && mv
|
||||
"$CONFIG".tmp "$CONFIG"
|
||||
sed -e 's/WEBSERVER_PORTS = [(4001, 4002)]/WEBSERVER_PORTS = [%game.webports%]/g' "$CONFIG" >
|
||||
"$CONFIG".tmp && mv "$CONFIG".tmp "$CONFIG"
|
||||
``````
|
||||
|
||||
```bash
|
||||
|
||||
# settings.py MySQL DB configuration
|
||||
echo Configuring Game Database...
|
||||
echo "" >> "$CONFIG"
|
||||
echo "######################################################################" >> "$CONFIG"
|
||||
echo "# MySQL Database Configuration" >> "$CONFIG"
|
||||
echo "######################################################################" >> "$CONFIG"
|
||||
|
||||
echo "DATABASES = {" >> "$CONFIG"
|
||||
echo " 'default': {" >> "$CONFIG"
|
||||
echo " 'ENGINE': 'django.db.backends.mysql'," >> "$CONFIG"
|
||||
echo " 'OPTIONS': {" >> "$CONFIG"
|
||||
echo " 'read_default_file': 'server/conf/my.cnf'," >> "$CONFIG"
|
||||
echo " }," >> "$CONFIG"
|
||||
echo " }" >> "$CONFIG"
|
||||
echo "}" >> "$CONFIG"
|
||||
|
||||
# Create the My.CNF file.
|
||||
echo "[client]" >> "$MYCONF"
|
||||
echo "database = %mysql.db%" >> "$MYCONF"
|
||||
echo "user = %mysql.user%" >> "$MYCONF"
|
||||
echo "password = %mysql.pass%" >> "$MYCONF"
|
||||
echo "default-character-set = utf8" >> "$MYCONF"
|
||||
|
||||
```
|
||||
|
||||
If you look at the parameters side of the page after saving this script, you'll notice that some new
|
||||
parameters have been populated for you. This is because we've included new teamcity configuration
|
||||
parameters that are populated when the build itself is ran. When creating projects that inherit this
|
||||
template, we'll be able to fill in or override those parameters for project-specific configuration.
|
||||
|
||||
Go ahead and create another build step called "Make Database Migration"
|
||||
If you're using Sqlite3 for your game (default database), it's prudent to change working directory on this
|
||||
step to your game dir.
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# Update the DB migration
|
||||
|
||||
LOGDIR="server/logs"
|
||||
|
||||
. %evenv.dir%/bin/activate
|
||||
|
||||
# Check that the logs directory exists.
|
||||
if [ ! -d "$LOGDIR" ]; then
|
||||
# Control will enter here if $LOGDIR doesn't exist.
|
||||
mkdir "$LOGDIR"
|
||||
fi
|
||||
|
||||
evennia makemigrations
|
||||
```
|
||||
|
||||
Create yet another build step, this time named: "Execute Database Migration":
|
||||
If you're using Sqlite3 for your game (default database), it's prudent to change working directory on this
|
||||
step to your game dir.
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# Apply the database migration.
|
||||
|
||||
LOGDIR="server/logs"
|
||||
|
||||
. %evenv.dir%/bin/activate
|
||||
|
||||
# Check that the logs directory exists.
|
||||
if [ ! -d "$LOGDIR" ]; then
|
||||
# Control will enter here if $LOGDIR doesn't exist.
|
||||
mkdir "$LOGDIR"
|
||||
fi
|
||||
|
||||
evennia migrate
|
||||
|
||||
```
|
||||
|
||||
Our next build step is where we actually publish our build. Up until now, all work on game has been
|
||||
done in a 'work' directory on TeamCity's build agent. From that directory we will now copy our files
|
||||
to where our game actually exists on the local server.
|
||||
|
||||
Create a new build step called "Publish Build". If you're using SQlite3 on your game, be sure to order this step ABOVE
|
||||
the Database Migration steps. The build order will matter!
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# Publishes the build to the proper build directory.
|
||||
|
||||
DIRECTORY="<game_dir>"
|
||||
|
||||
if [ ! -d "$DIRECTORY" ]; then
|
||||
# Control will enter here if $DIRECTORY doesn't exist.
|
||||
mkdir "$DIRECTORY"
|
||||
fi
|
||||
|
||||
# Copy all the files.
|
||||
cp -ruv %teamcity.build.checkoutDir%/* "$DIRECTORY"
|
||||
chmod -R 775 "$DIRECTORY"
|
||||
|
||||
```
|
||||
|
||||
Finally the last script will reload our game for us.
|
||||
|
||||
Create a new script called "Reload Game":
|
||||
The working directory on this build step will be: `%game.dir%`
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# Apply the database migration.
|
||||
|
||||
LOGDIR="server/logs"
|
||||
PIDDIR="server/server.pid"
|
||||
|
||||
. %evenv.dir%/bin/activate
|
||||
|
||||
# Check that the logs directory exists.
|
||||
if [ ! -d "$LOGDIR" ]; then
|
||||
# Control will enter here if $LOGDIR doesn't exist.
|
||||
mkdir "$LOGDIR"
|
||||
fi
|
||||
|
||||
# Check that the server is running.
|
||||
if [ -d "$PIDDIR" ]; then
|
||||
# Control will enter here if the game is running.
|
||||
evennia reload
|
||||
fi
|
||||
```
|
||||
|
||||
Now the template is ready for use! It would be useful this time to revisit the parameters page and
|
||||
set the evenv parameter to the directory where your virtualenv exists: IE "/srv/mush/evenv".
|
||||
|
||||
### Creating the Project
|
||||
|
||||
Now it's time for the last few steps to set up a CI environment.
|
||||
|
||||
* Return to the Evennia Project overview/administration page.
|
||||
* Create a new Sub-Project called "Production". This will be the category that holds our actual game.
|
||||
* Create a new Build Configuration in Production with the name of your MUSH. Base this configuration off of the
|
||||
continuous-integration template we made earlier.
|
||||
* In the build configuration, enter VCS roots and create a new VCS root that points to the
|
||||
branch/version control that you are using.
|
||||
* Go to the parameters page and fill in the undefined parameters for your specific configuration.
|
||||
* If you wish for the CI to run every time a commit is made, go to the VCS triggers and add one for
|
||||
"On Every Commit".
|
||||
|
||||
And you're done! At this point, you can return to the project overview page and queue a new build
|
||||
for your game. If everything was set up correctly, the build will complete successfully. Additional
|
||||
build steps could be added or removed at this point, adding some features like Unit Testing or more!
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
# Continuous integration with Travis
|
||||
|
||||
[Travis CI](https://travis-ci.org/) is an online service for checking, validating and potentially
|
||||
deploying code automatically. It can check that every commit is building successfully after every
|
||||
commit to its Github repository.
|
||||
|
||||
If your game is open source on Github you may use Travis for free.
|
||||
See [the Travis docs](https://docs.travis-ci.com/user/getting- started/) for how to get started.
|
||||
|
||||
After logging in you will get to point Travis to your repository on github. One further thing you
|
||||
need to set up yourself is a Travis config file named `.travis.yml` (note the initial period `.`).
|
||||
This should be created in the root of your game directory. The idea with this file is that it
|
||||
describes what Travis needs to import and build in order to create an instance of Evennia from
|
||||
scratch and then run validation tests on it. Here is an example:
|
||||
|
||||
``` yaml
|
||||
language: python
|
||||
python:
|
||||
- "3.10"
|
||||
install:
|
||||
- git clone https://github.com/evennia/evennia.git
|
||||
- cd evennia
|
||||
- pip install -e .
|
||||
- cd $TRAVIS_BUILD_DIR
|
||||
script:
|
||||
- evennia migrate
|
||||
- evennia test --settings settings.py .
|
||||
```
|
||||
|
||||
This will tell travis how to download Evennia, install it, set up a database and then run
|
||||
your own test suite (inside the game dir). Use `evennia test evennia` if you also want to
|
||||
run the Evennia full test suite.
|
||||
|
||||
You need to add this file to git (`git add .travis.yml`) and then commit your changes before Travis
|
||||
will be able to see it.
|
||||
|
||||
For properly testing your game you of course also need to write unittests.
|
||||
The [Unit testing](./Unit-Testing.md) doc page gives some ideas on how to set those up for Evennia.
|
||||
You should be able to refer to that for making tests fitting your game.
|
||||
28
docs/1.x/_sources/Coding/Continuous-Integration.md.txt
Normal file
28
docs/1.x/_sources/Coding/Continuous-Integration.md.txt
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
# Continuous Integration (CI)
|
||||
|
||||
[Continuous Integration (CI)](https://www.thoughtworks.com/continuous-integration) is a development practice that requires developers to integrate code into a shared repository. Each check-in is then verified by an automated build, allowing teams to detect problems early. This can be set up to safely deploy data to a production server only after tests have passed, for example.
|
||||
|
||||
For Evennia, continuous integration allows an automated build process to:
|
||||
|
||||
* Pull down a latest build from Source Control.
|
||||
* Run migrations on the backing SQL database.
|
||||
* Automate additional unique tasks for that project.
|
||||
* Run unit tests.
|
||||
* Publish those files to the server directory
|
||||
* Reload the game.
|
||||
|
||||
## Continuous-Integration guides
|
||||
|
||||
There are a lot of tools and services providing CI functionality. Here are a few that people have used with Evennia:
|
||||
|
||||
```{toctree}
|
||||
:maxdepth: 1
|
||||
|
||||
Continuous-Integration-Travis.md
|
||||
Continuous-Integration-TeamCity.md
|
||||
|
||||
```
|
||||
|
||||
- Evennia is itself making heavy use of [github actions]()
|
||||
|
||||
[This is an overview of other tools](https://www.atlassian.com/continuous-delivery/continuous-integration/tools) (external link).
|
||||
254
docs/1.x/_sources/Coding/Debugging.md.txt
Normal file
254
docs/1.x/_sources/Coding/Debugging.md.txt
Normal file
|
|
@ -0,0 +1,254 @@
|
|||
# Debugging
|
||||
|
||||
Sometimes, an error is not trivial to resolve. A few simple `print` statements is not enough to find the cause of the issue. The traceback is not informative or even non-existing.
|
||||
|
||||
Running a *debugger* can then be very helpful and save a lot of time. Debugging means running Evennia under control of a special *debugger* program. This allows you to stop the action at a given point, view the current state and step forward through the program to see how its logic works.
|
||||
|
||||
Evennia natively supports these debuggers:
|
||||
|
||||
- [Pdb](https://docs.python.org/2/library/pdb.html) is a part of the Python distribution and
|
||||
available out-of-the-box.
|
||||
- [PuDB](https://pypi.org/project/pudb/) is a third-party debugger that has a slightly more
|
||||
'graphical', curses-based user interface than pdb. It is installed with `pip install pudb`.
|
||||
|
||||
## Debugging Evennia
|
||||
|
||||
To run Evennia with the debugger, follow these steps:
|
||||
|
||||
1. Find the point in the code where you want to have more insight. Add the following line at that
|
||||
point.
|
||||
```python
|
||||
from evennia import set_trace;set_trace()
|
||||
```
|
||||
2. (Re-)start Evennia in interactive (foreground) mode with `evennia istart`. This is important - without this step the debugger will not start correctly - it will start in this interactive terminal.
|
||||
3. Perform the steps that will trigger the line where you added the `set_trace()` call. The debugger will start in the terminal from which Evennia was interactively started.
|
||||
|
||||
The `evennia.set_trace` function takes the following arguments:
|
||||
|
||||
|
||||
```python
|
||||
evennia.set_trace(debugger='auto', term_size=(140, 40))
|
||||
```
|
||||
|
||||
Here, `debugger` is one of `pdb`, `pudb` or `auto`. If `auto`, use `pudb` if available, otherwise use `pdb`. The `term_size` tuple sets the viewport size for `pudb` only (it's ignored by `pdb`).
|
||||
|
||||
|
||||
## A simple example using pdb
|
||||
|
||||
The debugger is useful in different cases, but to begin with, let's see it working in a command.
|
||||
Add the following test command (which has a range of deliberate errors) and also add it to your
|
||||
default cmdset. Then restart Evennia in interactive mode with `evennia istart`.
|
||||
|
||||
|
||||
```python
|
||||
# In file commands/command.py
|
||||
|
||||
|
||||
class CmdTest(Command):
|
||||
|
||||
"""
|
||||
A test command just to test pdb.
|
||||
|
||||
Usage:
|
||||
test
|
||||
|
||||
"""
|
||||
|
||||
key = "test"
|
||||
|
||||
def func(self):
|
||||
from evennia import set_trace; set_trace() # <--- start of debugger
|
||||
obj = self.search(self.args)
|
||||
self.msg("You've found {}.".format(obj.get_display_name()))
|
||||
|
||||
```
|
||||
|
||||
If you type `test` in your game, everything will freeze. You won't get any feedback from the game, and you won't be able to enter any command (nor anyone else). It's because the debugger has started in your console, and you will find it here. Below is an example with `pdb`.
|
||||
|
||||
```
|
||||
...
|
||||
> .../mygame/commands/command.py(79)func()
|
||||
-> obj = self.search(self.args)
|
||||
(Pdb)
|
||||
|
||||
```
|
||||
|
||||
`pdb` notes where it has stopped execution and, what line is about to be executed (in our case, `obj = self.search(self.args)`), and ask what you would like to do.
|
||||
|
||||
### Listing surrounding lines of code
|
||||
|
||||
When you have the `pdb` prompt `(Pdb)`, you can type in different commands to explore the code. The first one you should know is `list` (you can type `l` for short):
|
||||
|
||||
```
|
||||
(Pdb) l
|
||||
43
|
||||
44 key = "test"
|
||||
45
|
||||
46 def func(self):
|
||||
47 from evennia import set_trace; set_trace() # <--- start of debugger
|
||||
48 -> obj = self.search(self.args)
|
||||
49 self.msg("You've found {}.".format(obj.get_display_name()))
|
||||
50
|
||||
51 # -------------------------------------------------------------
|
||||
52 #
|
||||
53 # The default commands inherit from
|
||||
(Pdb)
|
||||
```
|
||||
|
||||
Okay, this didn't do anything spectacular, but when you become more confident with `pdb` and find yourself in lots of different files, you sometimes need to see what's around in code. Notice that there is a little arrow (`->`) before the line that is about to be executed.
|
||||
|
||||
This is important: **about to be**, not **has just been**. You need to tell `pdb` to go on (we'll soon see how).
|
||||
|
||||
### Examining variables
|
||||
|
||||
`pdb` allows you to examine variables (or really, to run any Python instruction). It is very useful to know the values of variables at a specific line. To see a variable, just type its name (as if you were in the Python interpreter:
|
||||
|
||||
```
|
||||
(Pdb) self
|
||||
<commands.command.CmdTest object at 0x045A0990>
|
||||
(Pdb) self.args
|
||||
u''
|
||||
(Pdb) self.caller
|
||||
<Character: XXX>
|
||||
(Pdb)
|
||||
```
|
||||
|
||||
If you try to see the variable `obj`, you'll get an error:
|
||||
|
||||
```
|
||||
(Pdb) obj
|
||||
*** NameError: name 'obj' is not defined
|
||||
(Pdb)
|
||||
```
|
||||
|
||||
That figures, since at this point, we haven't created the variable yet.
|
||||
|
||||
> Examining variable in this way is quite powerful. You can even run Python code and keep on
|
||||
> executing, which can help to check that your fix is actually working when you have identified an
|
||||
> error. If you have variable names that will conflict with `pdb` commands (like a `list`
|
||||
> variable), you can prefix your variable with `!`, to tell `pdb` that what follows is Python code.
|
||||
|
||||
### Executing the current line
|
||||
|
||||
It's time we asked `pdb` to execute the current line. To do so, use the `next` command. You can
|
||||
shorten it by just typing `n`:
|
||||
|
||||
```
|
||||
(Pdb) n
|
||||
AttributeError: "'CmdTest' object has no attribute 'search'"
|
||||
> .../mygame/commands/command.py(79)func()
|
||||
-> obj = self.search(self.args)
|
||||
(Pdb)
|
||||
```
|
||||
|
||||
`Pdb` is complaining that you try to call the `search` method on a command... whereas there's no `search` method on commands. The character executing the command is in `self.caller`, so we might change our line:
|
||||
|
||||
```python
|
||||
obj = self.caller.search(self.args)
|
||||
```
|
||||
|
||||
### Letting the program run
|
||||
|
||||
`pdb` is waiting to execute the same instruction... it provoked an error but it's ready to try again, just in case. We have fixed it in theory, but we need to reload, so we need to enter a command. To tell `pdb` to terminate and keep on running the program, use the `continue` (or `c`) command:
|
||||
|
||||
```
|
||||
(Pdb) c
|
||||
...
|
||||
```
|
||||
|
||||
You see an error being caught, that's the error we have fixed... or hope to have. Let's reload the game and try again. You need to run `evennia istart` again and then run `test` to get into the command again.
|
||||
|
||||
```
|
||||
> .../mygame/commands/command.py(79)func()
|
||||
-> obj = self.caller.search(self.args)
|
||||
(Pdb)
|
||||
|
||||
```
|
||||
|
||||
`pdb` is about to run the line again.
|
||||
|
||||
```
|
||||
(Pdb) n
|
||||
> .../mygame/commands/command.py(80)func()
|
||||
-> self.msg("You've found {}.".format(obj.get_display_name()))
|
||||
(Pdb)
|
||||
```
|
||||
|
||||
This time the line ran without error. Let's see what is in the `obj` variable:
|
||||
|
||||
```
|
||||
(Pdb) obj
|
||||
(Pdb) print obj
|
||||
None
|
||||
(Pdb)
|
||||
```
|
||||
|
||||
We have entered the `test` command without parameter, so no object could be found in the search
|
||||
(`self.args` is an empty string).
|
||||
|
||||
Let's allow the command to continue and try to use an object name as parameter (although, we should
|
||||
fix that bug too, it would be better):
|
||||
|
||||
```
|
||||
(Pdb) c
|
||||
...
|
||||
```
|
||||
|
||||
Notice that you'll have an error in the game this time. Let's try with a valid parameter. I have another character, `barkeep`, in this room:
|
||||
|
||||
```test barkeep```
|
||||
|
||||
And again, the command freezes, and we have the debugger opened in the console.
|
||||
|
||||
Let's execute this line right away:
|
||||
|
||||
```
|
||||
> .../mygame/commands/command.py(79)func()
|
||||
-> obj = self.caller.search(self.args)
|
||||
(Pdb) n
|
||||
> .../mygame/commands/command.py(80)func()
|
||||
-> self.msg("You've found {}.".format(obj.get_display_name()))
|
||||
(Pdb) obj
|
||||
<Character: barkeep>
|
||||
(Pdb)
|
||||
```
|
||||
|
||||
At least this time we have found the object. Let's process...
|
||||
|
||||
```
|
||||
(Pdb) n
|
||||
TypeError: 'get_display_name() takes exactly 2 arguments (1 given)'
|
||||
> .../mygame/commands/command.py(80)func()
|
||||
-> self.msg("You've found {}.".format(obj.get_display_name()))
|
||||
(Pdb)
|
||||
```
|
||||
|
||||
As an exercise, fix this error, reload and run the debugger again. Nothing better than some experimenting!
|
||||
|
||||
Your debugging will often follow the same strategy:
|
||||
|
||||
1. Receive an error you don't understand.
|
||||
2. Put a breaking point **BEFORE** the error occurs.
|
||||
3. Run `evennia istart`
|
||||
4. Run the code again and see the debugger open.
|
||||
5. Run the program line by line, examining variables, checking the logic of instructions.
|
||||
6. Continue and try again, each step a bit further toward the truth and the working feature.
|
||||
|
||||
## Cheat-sheet of pdb/pudb commands
|
||||
|
||||
PuDB and Pdb share the same commands. The only real difference is how it's presented. The `look`
|
||||
command is not needed much in `pudb` since it displays the code directly in its user interface.
|
||||
|
||||
| Pdb/PuDB command | To do what |
|
||||
| ----------- | ---------- |
|
||||
| list (or l) | List the lines around the point of execution (not needed for `pudb`, it will show
|
||||
this directly). |
|
||||
| print (or p) | Display one or several variables. |
|
||||
| `!` | Run Python code (using a `!` is often optional). |
|
||||
| continue (or c) | Continue execution and terminate the debugger for this time. |
|
||||
| next (or n) | Execute the current line and goes to the next one. |
|
||||
| step (or s) | Step inside of a function or method to examine it. |
|
||||
| `<RETURN>` | Repeat the last command (don't type `n` repeatedly, just type it once and then press
|
||||
`<RETURN>` to repeat it). |
|
||||
|
||||
If you want to learn more about debugging with Pdb, you will find an [interesting tutorial on that topic here](https://pymotw.com/3/pdb/).
|
||||
24
docs/1.x/_sources/Coding/Default-Command-Syntax.md.txt
Normal file
24
docs/1.x/_sources/Coding/Default-Command-Syntax.md.txt
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
# Default Command Syntax
|
||||
|
||||
|
||||
Evennia allows for any command syntax.
|
||||
|
||||
If you like the way DikuMUDs, LPMuds or MOOs handle things, you could emulate that with Evennia. If you are ambitious you could even design a whole new style, perfectly fitting your own dreams of the ideal game. See the [Command](../Components/Commands.md) documentation for how to do this.
|
||||
|
||||
We do offer a default however. The default Evennia setup tends to *resemble* [MUX2](https://www.tinymux.org/), and its cousins [PennMUSH](https://www.pennmush.org), [TinyMUSH](https://github.com/TinyMUSH/TinyMUSH/wiki), and [RhostMUSH](http://www.rhostmush.com/):
|
||||
|
||||
```
|
||||
command[/switches] object [= options]
|
||||
```
|
||||
|
||||
While the reason for this similarity is partly historical, these codebases offer very mature feature sets for administration and building.
|
||||
|
||||
Evennia is *not* a MUX system though. It works very differently in many ways. For example, Evennia
|
||||
deliberately lacks an online softcode language (a policy explained on our [softcode policy page](./Soft-Code.md)). Evennia also does not shy from using its own syntax when deemed appropriate: the
|
||||
MUX syntax has grown organically over a long time and is, frankly, rather arcane in places. All in
|
||||
all the default command syntax should at most be referred to as "MUX-like" or "MUX-inspired".
|
||||
|
||||
```{toctree}
|
||||
:hidden:
|
||||
Soft-Code
|
||||
```
|
||||
278
docs/1.x/_sources/Coding/Evennia-Code-Style.md.txt
Normal file
278
docs/1.x/_sources/Coding/Evennia-Code-Style.md.txt
Normal file
|
|
@ -0,0 +1,278 @@
|
|||
# Evennia Code Style
|
||||
|
||||
All code submitted or committed to the Evennia project should aim to follow the
|
||||
guidelines outlined in [Python PEP 8][pep8]. Keeping the code style uniform
|
||||
makes it much easier for people to collaborate and read the code.
|
||||
|
||||
A good way to check if your code follows PEP8 is to use the [PEP8 tool][pep8tool]
|
||||
on your sources.
|
||||
|
||||
## Main code style specification
|
||||
|
||||
* 4-space indentation, NO TABS!
|
||||
* Unix line endings.
|
||||
* 100 character line widths
|
||||
* CamelCase is only used for classes, nothing else.
|
||||
* All non-global variable names and all function names are to be
|
||||
lowercase, words separated by underscores. Variable names should
|
||||
always be more than two letters long.
|
||||
* Module-level global variables (only) are to be in CAPITAL letters.
|
||||
* Imports should be done in this order:
|
||||
- Python modules (builtins and standard library)
|
||||
- Twisted modules
|
||||
- Django modules
|
||||
- Evennia library modules (`evennia`)
|
||||
- Evennia contrib modules (`evennia.contrib`)
|
||||
* All modules, classes, functions and methods should have doc strings formatted
|
||||
as outlined below.
|
||||
* All default commands should have a consistent docstring formatted as
|
||||
outlined below.
|
||||
|
||||
## Code Docstrings
|
||||
|
||||
All modules, classes, functions and methods should have docstrings
|
||||
formatted with [Google style][googlestyle] -inspired indents, using
|
||||
[Markdown][githubmarkdown] formatting where needed. Evennia's `api2md`
|
||||
parser will use this to create pretty API documentation.
|
||||
|
||||
|
||||
### Module docstrings
|
||||
|
||||
Modules should all start with at least a few lines of docstring at
|
||||
their top describing the contents and purpose of the module.
|
||||
|
||||
Example of module docstring (top of file):
|
||||
|
||||
```python
|
||||
"""
|
||||
This module handles the creation of `Objects` that
|
||||
are useful in the game ...
|
||||
|
||||
"""
|
||||
```
|
||||
|
||||
Sectioning (`# title`, `## subtile` etc) should not be used in
|
||||
freeform docstrings - this will confuse the sectioning of the auto
|
||||
documentation page and the auto-api will create this automatically.
|
||||
Write just the section name bolded on its own line to mark a section.
|
||||
Beyond sections markdown should be used as needed to format
|
||||
the text.
|
||||
|
||||
Code examples should use [multi-line syntax highlighting][markdown-hilight]
|
||||
to mark multi-line code blocks, using the "python" identifier. Just
|
||||
indenting code blocks (common in markdown) will not produce the
|
||||
desired look.
|
||||
|
||||
When using any code tags (inline or blocks) it's recommended that you
|
||||
don't let the code extend wider than about 70 characters or it will
|
||||
need to be scrolled horizontally in the wiki (this does not affect any
|
||||
other text, only code).
|
||||
|
||||
### Class docstrings
|
||||
|
||||
The root class docstring should describe the over-arching use of the
|
||||
class. It should usually not describe the exact call sequence nor list
|
||||
important methods, this tends to be hard to keep updated as the API
|
||||
develops. Don't use section markers (`#`, `##` etc).
|
||||
|
||||
Example of class docstring:
|
||||
|
||||
```python
|
||||
class MyClass(object):
|
||||
"""
|
||||
This class describes the creation of `Objects`. It is useful
|
||||
in many situations, such as ...
|
||||
|
||||
"""
|
||||
```
|
||||
|
||||
### Function / method docstrings
|
||||
|
||||
Example of function or method docstring:
|
||||
|
||||
```python
|
||||
|
||||
def funcname(a, b, c, d=False, **kwargs):
|
||||
"""
|
||||
This is a brief introduction to the function/class/method
|
||||
|
||||
Args:
|
||||
a (str): This is a string argument that we can talk about
|
||||
over multiple lines.
|
||||
b (int or str): Another argument.
|
||||
c (list): A list argument.
|
||||
d (bool, optional): An optional keyword argument.
|
||||
|
||||
Keyword Args:
|
||||
test (list): A test keyword.
|
||||
|
||||
Returns:
|
||||
str: The result of the function.
|
||||
|
||||
Raises:
|
||||
RuntimeException: If there is a critical error,
|
||||
this is raised.
|
||||
IOError: This is only raised if there is a
|
||||
problem with the database.
|
||||
|
||||
Notes:
|
||||
This is an example function. If `d=True`, something
|
||||
amazing will happen.
|
||||
|
||||
"""
|
||||
```
|
||||
|
||||
The syntax is very "loose" but the indentation matters. That is, you
|
||||
should end the block headers (like `Args:`) with a line break followed by
|
||||
an indent. When you need to break a line you should start the next line
|
||||
with another indent. For consistency with the code we recommend all
|
||||
indents to be 4 spaces wide (no tabs!).
|
||||
|
||||
Here are all the supported block headers:
|
||||
|
||||
```
|
||||
"""
|
||||
Args
|
||||
argname (freeform type): Description endind with period.
|
||||
Keyword Args:
|
||||
argname (freeform type): Description.
|
||||
Returns/Yields:
|
||||
type: Description.
|
||||
Raises:
|
||||
Exceptiontype: Description.
|
||||
Notes/Note/Examples/Example:
|
||||
Freeform text.
|
||||
"""
|
||||
```
|
||||
|
||||
Parts marked with "freeform" means that you can in principle put any
|
||||
text there using any formatting except for sections markers (`#`, `##`
|
||||
etc). You must also keep indentation to mark which block you are part
|
||||
of. You should normally use the specified format rather than the
|
||||
freeform counterpart (this will produce nicer output) but in some
|
||||
cases the freeform may produce a more compact and readable result
|
||||
(such as when describing an `*args` or `**kwargs` statement in general
|
||||
terms). The first `self` argument of class methods should never be
|
||||
documented.
|
||||
|
||||
Note that
|
||||
|
||||
```
|
||||
"""
|
||||
Args:
|
||||
argname (type, optional): Description.
|
||||
"""
|
||||
```
|
||||
|
||||
and
|
||||
|
||||
```
|
||||
"""
|
||||
Keyword Args:
|
||||
sargname (type): Description.
|
||||
"""
|
||||
```
|
||||
|
||||
mean the same thing! Which one is used depends on the function or
|
||||
method documented, but there are no hard rules; If there is a large
|
||||
`**kwargs` block in the function, using the `Keyword Args:` block may be a
|
||||
good idea, for a small number of arguments though, just using `Args:`
|
||||
and marking keywords as `optional` will shorten the docstring and make
|
||||
it easier to read.
|
||||
|
||||
## Default Command Docstrings
|
||||
|
||||
These represent a special case since Commands in Evennia use their class
|
||||
docstrings to represent the in-game help entry for that command.
|
||||
|
||||
All the commands in the _default command_ sets should have their doc-strings
|
||||
formatted on a similar form. For contribs, this is loosened, but if there is
|
||||
no particular reason to use a different form, one should aim to use the same
|
||||
style for contrib-command docstrings as well.
|
||||
|
||||
```python
|
||||
"""
|
||||
Short header
|
||||
|
||||
Usage:
|
||||
key[/switches, if any] <mandatory args> [optional] choice1||choice2||choice3
|
||||
|
||||
Switches:
|
||||
switch1 - description
|
||||
switch2 - description
|
||||
|
||||
Examples:
|
||||
Usage example and output
|
||||
|
||||
Longer documentation detailing the command.
|
||||
|
||||
"""
|
||||
```
|
||||
|
||||
- Two spaces are used for *indentation* in all default commands.
|
||||
- Square brackets `[ ]` surround *optional, skippable arguments*.
|
||||
- Angled brackets `< >` surround a _description_ of what to write rather than the exact syntax.
|
||||
- Explicit choices are separated by `|`. To avoid this being parsed as a color code, use `||` (this
|
||||
will come out as a single `|`) or put spaces around the character ("` | `") if there's plenty of room.
|
||||
- The `Switches` and `Examples` blocks are optional and based on the Command.
|
||||
|
||||
Here is the `nick` command as an example:
|
||||
|
||||
```python
|
||||
"""
|
||||
Define a personal alias/nick
|
||||
|
||||
Usage:
|
||||
nick[/switches] <nickname> = [<string>]
|
||||
alias ''
|
||||
|
||||
Switches:
|
||||
object - alias an object
|
||||
account - alias an account
|
||||
clearall - clear all your aliases
|
||||
list - show all defined aliases (also "nicks" works)
|
||||
|
||||
Examples:
|
||||
nick hi = say Hello, I'm Sarah!
|
||||
nick/object tom = the tall man
|
||||
|
||||
A 'nick' is a personal shortcut you create for your own use [...]
|
||||
|
||||
"""
|
||||
```
|
||||
|
||||
For commands that *require arguments*, the policy is for it to return a `Usage:`
|
||||
string if the command is entered without any arguments. So for such commands,
|
||||
the Command body should contain something to the effect of
|
||||
|
||||
```python
|
||||
if not self.args:
|
||||
self.caller.msg("Usage: nick[/switches] <nickname> = [<string>]")
|
||||
return
|
||||
```
|
||||
|
||||
## Tools for auto-linting
|
||||
|
||||
### black
|
||||
|
||||
Automatic pep8 compliant formatting and linting can be performed using the
|
||||
`black` formatter:
|
||||
|
||||
black --line-length 100
|
||||
|
||||
### PyCharm
|
||||
|
||||
The Python IDE [Pycharm][pycharm] can auto-generate empty doc-string stubs. The
|
||||
default is to use `reStructuredText` form, however. To change to Evennia's
|
||||
Google-style docstrings, follow [this guide][pycharm-guide].
|
||||
|
||||
|
||||
|
||||
[pep8]: http://www.python.org/dev/peps/pep-0008
|
||||
[pep8tool]: https://pypi.python.org/pypi/pep8
|
||||
[googlestyle]: https://www.sphinx-doc.org/en/master/usage/extensions/example_google.html
|
||||
[githubmarkdown]: https://help.github.com/articles/github-flavored-markdown/
|
||||
[markdown-hilight]: https://help.github.com/articles/github-flavored-markdown/#syntax-highlighting
|
||||
[command-docstrings]: https://github.com/evennia/evennia/wiki/Using%20MUX%20As%20a%20Standard#documentation-policy
|
||||
[pycharm]: https://www.jetbrains.com/pycharm/
|
||||
[pycharm-guide]: https://www.jetbrains.com/help/pycharm/2016.3/python-integrated-tools.html
|
||||
197
docs/1.x/_sources/Coding/Profiling.md.txt
Normal file
197
docs/1.x/_sources/Coding/Profiling.md.txt
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
# Profiling
|
||||
|
||||
```{important}
|
||||
This is considered an advanced topic. It's mainly of interest to server developers.
|
||||
```
|
||||
|
||||
Sometimes it can be useful to try to determine just how efficient a particular piece of code is, or to figure out if one could speed up things more than they are. There are many ways to test the performance of Python and the running server.
|
||||
|
||||
Before digging into this section, remember Donald Knuth's [words of wisdom](https://en.wikipedia.org/wiki/Program_optimization#When_to_optimize):
|
||||
|
||||
> *[...]about 97% of the time: Premature optimization is the root of all evil*.
|
||||
|
||||
That is, don't start to try to optimize your code until you have actually identified a need to do so. This means your code must actually be working before you start to consider optimization. Optimization will also often make your code more complex and harder to read. Consider readability and maintainability and you may find that a small gain in speed is just not worth it.
|
||||
|
||||
## Simple timer tests
|
||||
|
||||
Python's `timeit` module is very good for testing small things. For example, in
|
||||
order to test if it is faster to use a `for` loop or a list comprehension you
|
||||
could use the following code:
|
||||
|
||||
```python
|
||||
import timeit
|
||||
# Time to do 1000000 for loops
|
||||
timeit.timeit("for i in range(100):\n a.append(i)", setup="a = []")
|
||||
<<< 10.70982813835144
|
||||
# Time to do 1000000 list comprehensions
|
||||
timeit.timeit("a = [i for i in range(100)]")
|
||||
<<< 5.358283996582031
|
||||
```
|
||||
|
||||
The `setup` keyword is used to set up things that should not be included in the time measurement, like `a = []` in the first call.
|
||||
|
||||
By default the `timeit` function will re-run the given test 1000000 times and returns the *total time* to do so (so *not* the average per test). A hint is to not use this default for testing something that includes database writes - for that you may want to use a lower number of repeats (say 100 or 1000) using the `number=100` keyword.
|
||||
|
||||
In the example above, we see that this number of calls, using a list comprehension is about twice as fast as building a list using `.append()`.
|
||||
|
||||
## Using cProfile
|
||||
|
||||
Python comes with its own profiler, named cProfile (this is for cPython, no tests have been done with `pypy` at this point). Due to the way Evennia's processes are handled, there is no point in using the normal way to start the profiler (`python -m cProfile evennia.py`). Instead you start the profiler through the launcher:
|
||||
|
||||
evennia --profiler start
|
||||
|
||||
This will start Evennia with the Server component running (in daemon mode) under cProfile. You could instead try `--profile` with the `portal` argument to profile the Portal (you would then need to [start the Server separately](../Setup/Running-Evennia.md)).
|
||||
|
||||
Please note that while the profiler is running, your process will use a lot more memory than usual. Memory usage is even likely to climb over time. So don't leave it running perpetually but monitor it carefully (for example using the `top` command on Linux or the Task Manager's memory display on Windows).
|
||||
|
||||
Once you have run the server for a while, you need to stop it so the profiler can give its report. Do *not* kill the program from your task manager or by sending it a kill signal - this will most likely also mess with the profiler. Instead either use `evennia.py stop` or (which may be even better), use `@shutdown` from inside the game.
|
||||
|
||||
Once the server has fully shut down (this may be a lot slower than usual) you will find that profiler has created a new file `mygame/server/logs/server.prof`.
|
||||
|
||||
### Analyzing the profile
|
||||
|
||||
The `server.prof` file is a binary file. There are many ways to analyze and display its contents, all of which has only been tested in Linux (If you are a Windows/Mac user, let us know what works).
|
||||
|
||||
You can look at the contents of the profile file with Python's in-built `pstats` module in the evennia shell (it's recommended you install `ipython` with `pip install ipython` in your virtualenv first, for prettier output):
|
||||
|
||||
evennia shell
|
||||
|
||||
Then in the shell
|
||||
|
||||
```python
|
||||
import pstats
|
||||
from pstats import SortKey
|
||||
|
||||
p = pstats.Stats('server/log/server.prof')
|
||||
p.strip_dirs().sort_stats(-1).print_stats()
|
||||
|
||||
```
|
||||
|
||||
See the [Python profiling documentation](https://docs.python.org/3/library/profile.html#instant-user-s-manual) for more information.
|
||||
|
||||
You can also visualize the data in various ways.
|
||||
- [Runsnake](https://pypi.org/project/RunSnakeRun/) visualizes the profile to
|
||||
give a good overview. Install with `pip install runsnakerun`. Note that this
|
||||
may require a C compiler and be quite slow to install.
|
||||
- For more detailed listing of usage time, you can use
|
||||
[KCachegrind](http://kcachegrind.sourceforge.net/html/Home.html). To make
|
||||
KCachegrind work with Python profiles you also need the wrapper script
|
||||
[pyprof2calltree](https://pypi.python.org/pypi/pyprof2calltree/). You can get
|
||||
`pyprof2calltree` via `pip` whereas KCacheGrind is something you need to get
|
||||
via your package manager or their homepage.
|
||||
|
||||
How to analyze and interpret profiling data is not a trivial issue and depends on what you are profiling for. Evennia being an asynchronous server can also confuse profiling. Ask on the mailing list if you need help and be ready to be able to supply your `server.prof` file for comparison, along with the exact conditions under which it was obtained.
|
||||
|
||||
## The Dummyrunner
|
||||
|
||||
It is difficult to test "actual" game performance without having players in your game. For this reason Evennia comes with the *Dummyrunner* system. The Dummyrunner is a stress-testing system: a separate program that logs into your game with simulated players (aka "bots" or "dummies"). Once connected, these dummies will semi-randomly perform various tasks from a list of possible actions. Use `Ctrl-C` to stop the Dummyrunner.
|
||||
|
||||
```{warning}
|
||||
|
||||
You should not run the Dummyrunner on a production database. It
|
||||
will spawn many objects and also needs to run with general permissions.
|
||||
|
||||
This is the recommended process for using the dummy runner:
|
||||
```
|
||||
|
||||
1. Stop your server completely with `evennia stop`.
|
||||
1. At _the end_ of your `mygame/server/conf.settings.py` file, add the line
|
||||
|
||||
from evennia.server.profiling.settings_mixin import *
|
||||
|
||||
This will override your settings and disable Evennia's rate limiters and DoS-protections, which would otherwise block mass-connecting clients from one IP. Notably, it will also change to a different (faster) password hasher.
|
||||
1. (recommended): Build a new database. If you use default Sqlite3 and want to
|
||||
keep your existing database, just rename `mygame/server/evennia.db3` to
|
||||
`mygame/server/evennia.db3_backup` and run `evennia migrate` and `evennia
|
||||
start` to create a new superuser as usual.
|
||||
1. (recommended) Log into the game as your superuser. This is just so you
|
||||
can manually check response. If you kept an old database, you will _not_
|
||||
be able to connect with an _existing_ user since the password hasher changed!
|
||||
1. Start the dummyrunner with 10 dummy users from the terminal with
|
||||
|
||||
evennia --dummyrunner 10
|
||||
|
||||
Use `Ctrl-C` (or `Cmd-C`) to stop it.
|
||||
|
||||
If you want to see what the dummies are actually doing you can run with a single dummy:
|
||||
|
||||
evennia --dummyrunner 1
|
||||
|
||||
The inputs/outputs from the dummy will then be printed. By default the runner uses the 'looker' profile, which just logs in and sends the 'look' command over and over. To change the settings, copy the file `evennia/server/profiling/dummyrunner_settings.py` to your `mygame/server/conf/` directory, then add this line to your settings file to use it in the new location:
|
||||
|
||||
DUMMYRUNNER_SETTINGS_MODULE = "server/conf/dummyrunner_settings.py"
|
||||
|
||||
The dummyrunner settings file is a python code module in its own right - it defines the actions available to the dummies. These are just tuples of command strings (like "look here") for the dummy to send to the server along with a probability of them happening. The dummyrunner looks for a global variable `ACTIONS`, a list of tuples, where the first two elements define the commands for logging in/out of the server.
|
||||
|
||||
Below is a simplified minimal setup (the default settings file adds a lot more functionality and info):
|
||||
|
||||
```python
|
||||
# minimal dummyrunner setup file
|
||||
|
||||
# Time between each dummyrunner "tick", in seconds. Each dummy will be called
|
||||
# with this frequency.
|
||||
TIMESTEP = 1
|
||||
|
||||
# Chance of a dummy actually performing an action on a given tick. This
|
||||
# spreads out usage randomly, like it would be in reality.
|
||||
CHANCE_OF_ACTION = 0.5
|
||||
|
||||
# Chance of a currently unlogged-in dummy performing its login action every
|
||||
# tick. This emulates not all accounts logging in at exactly the same time.
|
||||
CHANCE_OF_LOGIN = 0.01
|
||||
|
||||
# Which telnet port to connect to. If set to None, uses the first default
|
||||
# telnet port of the running server.
|
||||
TELNET_PORT = None
|
||||
|
||||
# actions
|
||||
|
||||
def c_login(client):
|
||||
name = f"Character-{client.gid}"
|
||||
pwd = f"23fwsf23sdfw23wef23"
|
||||
return (
|
||||
f"create {name} {pwd}"
|
||||
f"connect {name} {pwd}"
|
||||
)
|
||||
|
||||
def c_logout(client):
|
||||
return ("quit", )
|
||||
|
||||
def c_look(client):
|
||||
return ("look here", "look me")
|
||||
|
||||
# this is read by dummyrunner.
|
||||
ACTIONS = (
|
||||
c_login,
|
||||
c_logout,
|
||||
(1.0, c_look) # (probability, command-generator)
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
At the bottom of the default file are a few default profiles you can test out by just setting the `PROFILE` variable to one of the options.
|
||||
|
||||
### Dummyrunner hints
|
||||
|
||||
- Don't start with too many dummies. The Dummyrunner taxes the server much more
|
||||
than 'real' users tend to do. Start with 10-100 to begin with.
|
||||
- Stress-testing can be fun, but also consider what a 'realistic' number of
|
||||
users would be for your game.
|
||||
- Note in the dummyrunner output how many commands/s are being sent to the
|
||||
server by all dummies. This is usually a lot higher than what you'd
|
||||
realistically expect to see from the same number of users.
|
||||
- The default settings sets up a 'lag' measure to measaure the round-about
|
||||
message time. It updates with an average every 30 seconds. It can be worth to
|
||||
have this running for a small number of dummies in one terminal before adding
|
||||
more by starting another dummyrunner in another terminal - the first one will
|
||||
act as a measure of how lag changes with different loads. Also verify the
|
||||
lag-times by entering commands manually in-game.
|
||||
- Check the CPU usage of your server using `top/htop` (linux). In-game, use the
|
||||
`server` command.
|
||||
- You can run the server with `--profiler start` to test it with dummies. Note
|
||||
that the profiler will itself affect server performance, especially memory
|
||||
consumption.
|
||||
- Generally, the dummyrunner system makes for a decent test of general
|
||||
performance; but it is of course hard to actually mimic human user behavior.
|
||||
For this, actual real-game testing is required.
|
||||
|
||||
151
docs/1.x/_sources/Coding/Release-Notes-1.0.md.txt
Normal file
151
docs/1.x/_sources/Coding/Release-Notes-1.0.md.txt
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
# Evennia 1.0 Release Notes
|
||||
|
||||
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
|
||||
|
||||
- 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.
|
||||
- Twisted 22.10+
|
||||
- Django 4.1+
|
||||
|
||||
## Major new features
|
||||
|
||||
- Evennia is now on PyPi and is installable as [pip install evennia](../Setup/Installation.md).
|
||||
- A completely revamped documentation at https://www.evennia.com/docs/latest. The old wiki and readmedocs pages will close.
|
||||
- Evennia 1.0 now has a REST API which allows you access game objects using CRUD operations GET/POST etc. See [The Web-API docs][Web-API] for more information.
|
||||
- [Evennia<>Discord Integration](../Setup/Channels-to-Discord.md) between Evennia channels and Discord servers.
|
||||
- [Script](../Components/Scripts.md) overhaul: Scripts' timer component independent from script object deletion; can now start/stop timer without deleting Script. The `.persistent` flag now only controls if timer survives reload - Script has to be removed with `.delete()` like other typeclassed entities. This makes Scripts even more useful as general storage entities.
|
||||
- The [FuncParser](../Components/FuncParser.md) centralizes and vastly improves all in-string function calls, such as `say the result is $eval(3 * 7)` and say the result `the result is 21`. The parser completely replaces the old `parse_inlinefunc`. The new parser can handle both arguments and kwargs and are also used for in-prototype parsing as well as director stance messaging, such as using `$You()` to represent yourself in a string and having the result come out differently depending on who see you.
|
||||
- [Channels](../Components/Channels.md) New Channel-System using the `channel` command and nicks. The old `ChannelHandler` was removed and the customization and operation of channels have been simplified a lot. The old command syntax commands are now available as a contrib.
|
||||
- [Help System](../Components/Help-System.md) was refactored.
|
||||
- A new type of `FileHelp` system allows you to add in-game help files as external Python files. This means there are three ways to add help entries in Evennia: 1) Auto-generated from Command's code. 2) Manually added to the database from the `sethelp` command in-game and 3) Created as external Python files that Evennia loads and makes available in-game.
|
||||
- We now use `lunr` search indexing for better `help` matching and suggestions. Also improve
|
||||
the main help command's default listing output.
|
||||
- Help command now uses `view` lock to determine if cmd/entry shows in index and `read` lock to determine if it can be read. It used to be `view` in the role of the latter.
|
||||
- `sethelp` command now warns if shadowing other help-types when creating a new entry.
|
||||
- Make `help` index output clickable for webclient/clients with MXP (PR by davewiththenicehat)
|
||||
- Rework of the [Web](../Components/Website.md) setup, into a much more consistent structure and update to latest Django. The `mygame/web/static_overrides` and `-template_overrides` were removed. The folders are now just `mygame/web/static` and `/templates` and handle the automatic copying of data behind the scenes. `app.css` to `website.css` for consistency. The old `prosimii-css` files were removed.
|
||||
- [AttributeProperty](../Components/Attributes.md#using-attributeproperty)/[TagProperty](../Components/Tags.md) along with `AliasProperty` and `PermissionProperty` to allow managing Attributes, Tags, Aliases and Permissios on typeclasses in the same way as Django fields. This dramatically reduces the need to assign Attributes/Tags in `at_create_object` hook.
|
||||
- The old `MULTISESSION_MODE` was divided into smaller settings, for better controlling what happens when a user connects, if a character should be auto-created, and how many characters they can control at the same time. See [Connection-Styles](../Concepts/Connection-Styles.md) for a detailed explanation.
|
||||
- Evennia now supports custom `evennia` launcher commands (e.g. `evennia mycmd foo bar`). Add new commands as callables accepting `*args`, as `settings.EXTRA_LAUNCHER_COMMANDS = {'mycmd': 'path.to.callable', ...}`.
|
||||
|
||||
|
||||
## Contribs
|
||||
|
||||
The `contrib` folder structure was changed from 0.9.5. All contribs are now in sub-folders and organized into categories. All import paths must be updated. See [Contribs overview](../Contribs/Contribs-Overview.md).
|
||||
|
||||
- New [Traits contrib](../Contribs/Contrib-Traits.md), converted and expanded from Ainneve project. (whitenoise, Griatch)
|
||||
- New [Crafting contrib](../Contribs/Contrib-Crafting.md), adding a full crafting subsystem (Griatch)
|
||||
- New [XYZGrid contrib](../Contribs/Contrib-XYZGrid.md), adding x,y,z grid coordinates with in-game map and pathfinding. Controlled outside of the game via custom evennia launcher command (Griatch)
|
||||
- New [Command cooldown contrib](../Contribs/Contrib-Cooldowns.md) contrib for making it easier to manage commands using
|
||||
dynamic cooldowns between uses (owllex)
|
||||
- New [Godot Protocol contrib](../Contribs/Contrib-Godotwebsocket.md) for connecting to Evennia from a client written in the open-source game engine [Godot](https://godotengine.org/) (ChrisLR).
|
||||
- New [name_generator contrib](../Contribs/Contrib-Name-Generator.md) for building random real-world based or fantasy-names based on phonetic rules (InspectorCaracal)
|
||||
- New [Buffs contrib](../Contribs/Contrib-Buffs.md) for managing temporary and permanent RPG status buffs effects (tegiminis)
|
||||
- The existing [RPSystem contrib](../Contribs/Contrib-RPSystem.md) was refactored and saw a speed boost (InspectorCaracal, other contributors)
|
||||
|
||||
## Translations
|
||||
|
||||
- New Latin (la) translation (jamalainm)
|
||||
- New German (de) translation (Zhuraj)
|
||||
- Updated Italian translation (rpolve)
|
||||
- Updated Swedish translation
|
||||
|
||||
## Utils
|
||||
|
||||
- New `utils.format_grid` for easily displaying long lists of items in a block. This is now used for the default help display.
|
||||
- Add `utils.repeat` and `utils.unrepeat` as shortcuts to TickerHandler add/remove, similar
|
||||
to how `utils.delay` is a shortcut for TaskHandler add.
|
||||
- Add `utils/verb_conjugation` for automatic verb conjugation (English only). This
|
||||
is useful for implementing actor-stance emoting for sending a string to different targets.
|
||||
- `utils.evmenu.ask_yes_no` is a helper function that makes it easy to ask a yes/no question
|
||||
to the user and respond to their input. This complements the existing `get_input` helper.
|
||||
- New `tasks` command for managing tasks started with `utils.delay` (PR by davewiththenicehat)
|
||||
- Add `.deserialize()` method to `_Saver*` structures to help completely
|
||||
decouple structures from database without needing separate import.
|
||||
- Add `run_in_main_thread` as a helper for those wanting to code server code
|
||||
from a web view.
|
||||
- Update `evennia.utils.logger` to use Twisted's new logging API. No change in Evennia API
|
||||
except more standard aliases logger.error/info/exception/debug etc can now be used.
|
||||
- Made `utils.iter_to_str` format prettier strings, using Oxford comma.
|
||||
- Move `create_*` functions into db managers, leaving `utils.create` only being
|
||||
wrapper functions (consistent with `utils.search`). No change of api otherwise.
|
||||
|
||||
## Locks
|
||||
|
||||
- New `search:` lock type used to completely hide an object from being found by
|
||||
the `DefaultObject.search` (`caller.search`) method. (CloudKeeper)
|
||||
- New default for `holds()` lockfunc - changed from default of `True` to default of `False` in order to disallow dropping nonsensical things (such as things you don't hold).
|
||||
|
||||
## Hook changes
|
||||
|
||||
- Changed all `at_before/after_*` hooks to `at_pre/post_*` for consistency
|
||||
across Evennia (the old names still work but are deprecated)
|
||||
- New `at_pre_object_leave(obj, destination)` method on `Objects`.
|
||||
- New `at_server_init()` hook called before all other startup hooks for all
|
||||
startup modes. Used for more generic overriding (volund)
|
||||
- New `at_pre_object_receive(obj, source_location)` method on Objects. Called on
|
||||
destination, mimicking behavior of `at_pre_move` hook - returning False will abort move.
|
||||
- `Object.normalize_name` and `.validate_name` added to (by default) enforce latinify
|
||||
on character name and avoid potential exploits using clever Unicode chars (trhr)
|
||||
- Make `object.search` support 'stacks=0' keyword - if ``>0``, the method will return
|
||||
N identical matches instead of triggering a multi-match error.
|
||||
- Add `tags.has()` method for checking if an object has a tag or tags (PR by ChrisLR)
|
||||
- Add `Msg.db_receiver_external` field to allowe external, string-id message-receivers.
|
||||
- Add `$pron()` and `$You()` inlinefuncs for pronoun parsing in actor-stance strings using `msg_contents`.
|
||||
|
||||
## Command changes
|
||||
|
||||
- Change default multi-match syntax from `1-obj`, `2-obj` to `obj-1`, `obj-2`, which seems to be what most expect.
|
||||
- Split `return_appearance` hook with helper methods and have it use a template
|
||||
string in order to make it easier to override.
|
||||
- Command executions now done on copies to make sure `yield` don't cause crossovers. Add
|
||||
`Command.retain_instance` flag for reusing the same command instance.
|
||||
- Allow sending messages with `page/tell` without a `=` if target name contains no spaces.
|
||||
- The `typeclass` command will now correctly search the correct database-table for the target
|
||||
obj (avoids mistakenly assigning an AccountDB-typeclass to a Character etc).
|
||||
- Merged `script` and `scripts` commands into one, for both managing global- and
|
||||
on-object Scripts. Moved `CmdScripts` and `CmdObjects` to `commands/default/building.py`.
|
||||
- The `channel` commands replace all old channel-related commands, such as `cset` etc
|
||||
- Expand `examine` command's code to much more extensible and modular. Show
|
||||
attribute categories and value types (when not strings).
|
||||
- Add ability to examine `/script` and `/channel` entities with `examine` command.
|
||||
- Add support for `$dbref()` and `$search` when assigning an Attribute value
|
||||
with the `set` command. This allows assigning real objects from in-game.
|
||||
- Have `type/force` default to `update`-mode rather than `reset`mode and add more verbose
|
||||
warning when using reset mode.
|
||||
|
||||
## Coding improvement highlights
|
||||
|
||||
- The db pickle-serializer now checks for methods `__serialize_dbobjs__` and `__deserialize_dbobjs__` to allow custom packing/unpacking of nested dbobjs, to allow storing in Attribute. See [Attributes](../Components/Attributes.md) documentation.
|
||||
- Add `ObjectParent` mixin to default game folder template as an easy, ready-made
|
||||
way to override features on all ObjectDB-inheriting objects easily.
|
||||
source location, mimicking behavior of `at_pre_move` hook - returning False will abort move.
|
||||
- New Unit test parent classes, for use both in Evenia core and in mygame. Restructured unit tests to always honor default settings.
|
||||
|
||||
|
||||
## Other
|
||||
|
||||
- Homogenize manager search methods to always return querysets and not sometimes querysets and sometimes lists.
|
||||
- Attribute/NAttribute got a homogenous representation, using intefaces, both
|
||||
`AttributeHandler` and `NAttributeHandler` has same api now.
|
||||
- Added `content_types` indexing to DefaultObject's ContentsHandler. (volund)
|
||||
- Made most of the networking classes such as Protocols and the SessionHandlers
|
||||
replaceable via `settings.py` for modding enthusiasts. (volund)
|
||||
- The `initial_setup.py` file can now be substituted in `settings.py` to customize
|
||||
initial game database state. (volund)
|
||||
- Make IP throttle use Django-based cache system for optional persistence (PR by strikaco)
|
||||
- In modules given by `settings.PROTOTYPE_MODULES`, spawner will now first look for a global
|
||||
list `PROTOTYPE_LIST` of dicts before loading all dicts in the module as prototypes.
|
||||
concept of a dynamically created `ChannelCmdSet`.
|
||||
- Prototypes now allow setting `prototype_parent` directly to a prototype-dict.
|
||||
This makes it easier when dynamically building in-module prototypes.
|
||||
- Make `@lazy_property` decorator create read/delete-protected properties. This is because it's used for handlers, and e.g. self.locks=[] is a common beginner mistake.
|
||||
- Change `settings.COMMAND_DEFAULT_ARG_REGEX` default from `None` to a regex meaning that
|
||||
a space or `/` must separate the cmdname and args. This better fits common expectations.
|
||||
- Add `settings.MXP_ENABLED=True` and `settings.MXP_OUTGOING_ONLY=True` as sane defaults, to avoid known security issues with players entering MXP links.
|
||||
- Made `MonitorHandler.add/remove` support `category` for monitoring Attributes with a category (before only key was used, ignoring category entirely).
|
||||
|
||||
|
||||
84
docs/1.x/_sources/Coding/Setting-up-PyCharm.md.txt
Normal file
84
docs/1.x/_sources/Coding/Setting-up-PyCharm.md.txt
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
# Setting up PyCharm with Evennia
|
||||
|
||||
[PyCharm](https://www.jetbrains.com/pycharm/) is a Python developer's IDE from Jetbrains available for Windows, Mac and Linux. It is a commercial product but offer free trials, a scaled-down community edition and also generous licenses for OSS projects like Evennia.
|
||||
|
||||
> This page was originally tested on Windows (so use Windows-style path examples), but should work the same for all platforms.
|
||||
|
||||
First, install Evennia on your local machine with [[Getting Started]]. If you're new to PyCharm, loading your project is as easy as selecting the `Open` option when PyCharm starts, and browsing to your game folder (the one created with `evennia --init`). We refer to it as `mygame` here.
|
||||
|
||||
If you want to be able to examine evennia's core code or the scripts inside your virtualenv, you'll
|
||||
need to add them to your project too:
|
||||
|
||||
1. Go to `File > Open...`
|
||||
1. Select the folder (i.e. the `evennia` root)
|
||||
1. Select "Open in current window" and "Add to currently opened projects"
|
||||
|
||||
It's a good idea to set up the interpreter this before attempting anything further. The rest of this page assumes your project is already configured in PyCharm.
|
||||
|
||||
1. Go to `File > Settings... > Project: \<mygame\> > Project Interpreter`
|
||||
1. Click the Gear symbol `> Add local`
|
||||
1. Navigate to your `evenv/scripts directory`, and select Python.exe
|
||||
|
||||
Enjoy seeing all your imports checked properly, setting breakpoints, and live variable watching!
|
||||
|
||||
## Debug Evennia from inside PyCharm
|
||||
|
||||
1. Launch Evennia in your preferred way (usually from a console/terminal)
|
||||
1. Open your project in PyCharm
|
||||
1. In the PyCharm menu, select `Run > Attach to Local Process...`
|
||||
1. From the list, pick the `twistd` process with the `server.py` parameter (Example: `twistd.exe --nodaemon --logfile=\<mygame\>\server\logs\server.log --python=\<evennia repo\>\evennia\server\server.py`)
|
||||
|
||||
Of course you can attach to the `portal` process as well. If you want to debug the Evennia launcher
|
||||
or runner for some reason (or just learn how they work!), see Run Configuration below.
|
||||
|
||||
> NOTE: Whenever you reload Evennia, the old Server process will die and a new one start. So when you restart you have to detach from the old and then reattach to the new process that was created.
|
||||
|
||||
> To make the process less tedious you can apply a filter in settings to show only the server.py process in the list. To do that navigate to: `Settings/Preferences | Build, Execution, Deployment | Python Debugger` and then in `Attach to process` field put in: `twistd.exe" --nodaemon`. This is an example for windows, I don't have a working mac/linux box.
|
||||
|
||||

|
||||
|
||||
## Run Evennia from inside PyCharm
|
||||
|
||||
This configuration allows you to launch Evennia from inside PyCharm. Besides convenience, it also allows suspending and debugging the evennia_launcher or evennia_runner at points earlier than you could by running them externally and attaching. In fact by the time the server and/or portal are running the launcher will have exited already.
|
||||
|
||||
1. Go to `Run > Edit Configutations...`
|
||||
1. Click the plus-symbol to add a new configuration and choose Python
|
||||
1. Add the script: `\<yourrepo\>\evenv\Scripts\evennia_launcher.py` (substitute your virtualenv if it's not named `evenv`)
|
||||
1. Set script parameters to: `start -l` (-l enables console logging)
|
||||
1. Ensure the chosen interpreter is from your virtualenv
|
||||
1. Set Working directory to your `mygame` folder (not evenv nor evennia)
|
||||
1. You can refer to the PyCharm documentation for general info, but you'll want to set at least a config name (like "MyMUD start" or similar).
|
||||
|
||||
Now set up a "stop" configuration by following the same steps as above, but set your Script parameters to: stop (and name the configuration appropriately).
|
||||
|
||||
A dropdown box holding your new configurations should appear next to your PyCharm run button. Select MyMUD start and press the debug icon to begin debugging. Depending on how far you let the program run, you may need to run your "MyMUD stop" config to actually stop the server, before you'll be able start it again.
|
||||
|
||||
### Alternative config - utilizing logfiles as source of data
|
||||
|
||||
This configuration takes a bit different approach as instead of focusing on getting the data back through logfiles. Reason for that is this way you can easily separate data streams, for example you rarely want to follow both server and portal at the same time, and this will allow it. This will also make sure to stop the evennia before starting it, essentially working as reload command (it will also include instructions how to disable that part of functionality). We will start by defining a configuration that will stop evennia. This assumes that `upfire` is your pycharm project name, and also the game name, hence the `upfire/upfire` path.
|
||||
|
||||
1. Go to `Run > Edit Configutations...`\
|
||||
1. Click the plus-symbol to add a new configuration and choose the python interpreter to use (should be project default)
|
||||
1. Name the configuration as "stop evennia" and fill rest of the fields accordingly to the image:
|
||||

|
||||
1. Press `Apply`
|
||||
|
||||
Now we will define the start/reload command that will make sure that evennia is not running already, and then start the server in one go.
|
||||
1. Go to `Run > Edit Configutations...`\
|
||||
1. Click the plus-symbol to add a new configuration and choose the python interpreter to use (should be project default)
|
||||
1. Name the configuration as "start evennia" and fill rest of the fields accordingly to the image:
|
||||

|
||||
1. Navigate to the `Logs` tab and add the log files you would like to follow. The picture shows
|
||||
adding `portal.log` which will show itself in `portal` tab when running:
|
||||

|
||||
1. Skip the following steps if you don't want the launcher to stop evennia before starting.
|
||||
1. Head back to `Configuration` tab and press the `+` sign at the bottom, under `Before launch....`
|
||||
and select `Run another configuration` from the submenu that will pop up.
|
||||
1. Click `stop evennia` and make sure that it's added to the list like on the image above.
|
||||
1. Click `Apply` and close the run configuration window.
|
||||
|
||||
You are now ready to go, and if you will fire up `start evennia` configuration you should see
|
||||
following in the bottom panel:
|
||||

|
||||
and you can click through the tabs to check appropriate logs, or even the console output as it is
|
||||
still running in interactive mode.
|
||||
67
docs/1.x/_sources/Coding/Soft-Code.md.txt
Normal file
67
docs/1.x/_sources/Coding/Soft-Code.md.txt
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
# Soft Code
|
||||
|
||||
|
||||
Softcode is a very simple programming language that was created for in-game development on TinyMUD derivatives such as MUX, PennMUSH, TinyMUSH, and RhostMUSH. The idea is that by providing a stripped down, minimalistic language for in-game use, you can allow quick and easy building and game development to happen without having to learn C/C++. There is an added benefit of not having to have to hand out shell access to all developers, and permissions can be used to alleviate many security problems.
|
||||
|
||||
Writing and installing softcode is done through a MUD client. Thus it is not a formatted language.
|
||||
Each softcode function is a single line of varying size. Some functions can be a half of a page long
|
||||
or more which is obviously not very readable nor (easily) maintainable over time.
|
||||
|
||||
## Examples of Softcode
|
||||
|
||||
Here is a simple 'Hello World!' command:
|
||||
|
||||
```bash
|
||||
@set me=HELLO_WORLD.C:$hello:@pemit %#=Hello World!
|
||||
```
|
||||
|
||||
Pasting this into a MUX/MUSH and typing 'hello' will theoretically yield 'Hello World!', assuming
|
||||
certain flags are not set on your account object.
|
||||
|
||||
Setting attributes is done via `@set`. Softcode also allows the use of the ampersand (`&`) symbol.
|
||||
This shorter version looks like this:
|
||||
|
||||
```bash
|
||||
&HELLO_WORLD.C me=$hello:@pemit %#=Hello World!
|
||||
```
|
||||
|
||||
Perhaps I want to break the Hello World into an attribute which is retrieved when emitting:
|
||||
|
||||
```bash
|
||||
&HELLO_VALUE.D me=Hello World
|
||||
&HELLO_WORLD.C me=$hello:@pemit %#=[v(HELLO_VALUE.D)]
|
||||
```
|
||||
|
||||
The `v()` function returns the `HELLO_VALUE.D` attribute on the object that the command resides
|
||||
(`me`, which is yourself in this case). This should yield the same output as the first example.
|
||||
|
||||
If you are still curious about how Softcode works, take a look at some external resources:
|
||||
|
||||
- https://wiki.tinymux.org/index.php/Softcode
|
||||
- https://www.duh.com/discordia/mushman/man2x1
|
||||
|
||||
## Problems with Softcode
|
||||
|
||||
Softcode is excellent at what it was intended for: *simple things*. It is a great tool for making an interactive object, a room with ambiance, simple global commands, simple economies and coded systems. However, once you start to try to write something like a complex combat system or a higher end economy, you're likely to find yourself buried under a mountain of functions that span multiple objects across your entire code.
|
||||
|
||||
Not to mention, softcode is not an inherently fast language. It is not compiled, it is parsed with each calling of a function. While MUX and MUSH parsers have jumped light years ahead of where they once were they can still stutter under the weight of more complex systems if not designed properly.
|
||||
|
||||
## Changing Times
|
||||
|
||||
Now that starting text-based games is easy and an option for even the most technically inarticulate, new projects are a dime a dozen. People are starting new MUDs every day with varying levels of commitment and ability. Because of this shift from fewer, larger, well-staffed games to a bunch of small, one or two developer games, some of the benefit of softcode fades.
|
||||
|
||||
Softcode is great in that it allows a mid to large sized staff all work on the same game without stepping on one another's toes. As mentioned before, shell access is not necessary to develop a MUX or a MUSH. However, now that we are seeing a lot more small, one or two-man shops, the issue of shell access and stepping on each other's toes is a lot less.
|
||||
|
||||
## Our Solution
|
||||
|
||||
Evennia shuns in-game softcode for on-disk Python modules. Python is a popular, mature and
|
||||
professional programming language. You code it using the conveniences of modern text editors.
|
||||
Evennia developers have access to the entire library of Python modules out there in the wild - not
|
||||
to mention the vast online help resources available. Python code is not bound to one-line functions
|
||||
on objects but complex systems may be organized neatly into real source code modules, sub-modules, or even broken out into entire Python packages as desired.
|
||||
|
||||
So what is *not* included in Evennia is a MUX/MOO-like online player-coding system. Advanced coding in Evennia is primarily intended to be done outside the game, in full-fledged Python modules. Advanced building is best handled by extending Evennia's command system with your own sophisticated building commands. We feel that with a small development team you are better off using a professional source-control system (svn, git, bazaar, mercurial etc) anyway.
|
||||
|
||||
## Your Solution
|
||||
|
||||
Adding advanced and flexible building commands to your game is easy and will probably be enough to satisfy most creative builders. However, if you really, *really* want to offer online coding, there is of course nothing stopping you from adding that to Evennia, no matter our recommendations. You could even re-implement MUX' softcode in Python should you be very ambitious. The [in-game-python](../Contribs/Contrib-Ingame-Python.md) is an optional pseudo-softcode plugin aimed at developers wanting to script their game from inside it.
|
||||
306
docs/1.x/_sources/Coding/Unit-Testing.md.txt
Normal file
306
docs/1.x/_sources/Coding/Unit-Testing.md.txt
Normal file
|
|
@ -0,0 +1,306 @@
|
|||
# Unit Testing
|
||||
|
||||
*Unit testing* means testing components of a program in isolation from each other to make sure every part works on its own before using it with others. Extensive testing helps avoid new updates causing unexpected side effects as well as alleviates general code rot (a more comprehensive wikipedia article on unit testing can be found [here](https://en.wikipedia.org/wiki/Unit_test)).
|
||||
|
||||
A typical unit test set calls some function or method with a given input, looks at the result and makes sure that this result looks as expected. Rather than having lots of stand-alone test programs, Evennia makes use of a central *test runner*. This is a program that gathers all available tests all over the Evennia source code (called *test suites*) and runs them all in one go. Errors and tracebacks are reported.
|
||||
|
||||
By default Evennia only tests itself. But you can also add your own tests to your game code and have Evennia run those for you.
|
||||
|
||||
## Running the Evennia test suite
|
||||
|
||||
To run the full Evennia test suite, go to your game folder and issue the command
|
||||
|
||||
evennia test evennia
|
||||
|
||||
This will run all the evennia tests using the default settings. You could also run only a subset of
|
||||
all tests by specifying a subpackage of the library:
|
||||
|
||||
evennia test evennia.commands.default
|
||||
|
||||
A temporary database will be instantiated to manage the tests. If everything works out you will see
|
||||
how many tests were run and how long it took. If something went wrong you will get error messages.
|
||||
If you contribute to Evennia, this is a useful sanity check to see you haven't introduced an
|
||||
unexpected bug.
|
||||
|
||||
## Running custom game-dir unit tests
|
||||
|
||||
If you have implemented your own tests for your game you can run them from your game dir
|
||||
with
|
||||
|
||||
evennia test --settings settings.py .
|
||||
|
||||
The period (`.`) means to run all tests found in the current directory and all subdirectories. You
|
||||
could also specify, say, `typeclasses` or `world` if you wanted to just run tests in those subdirs.
|
||||
|
||||
An important thing to note is that those tests will all be run using the _default Evennia settings_.
|
||||
To run the tests with your own settings file you must use the `--settings` option:
|
||||
|
||||
evennia test --settings settings.py .
|
||||
|
||||
The `--settings` option of Evennia takes a file name in the `mygame/server/conf` folder. It is
|
||||
normally used to swap settings files for testing and development. In combination with `test`, it
|
||||
forces Evennia to use this settings file over the default one.
|
||||
|
||||
You can also test specific things by giving their path
|
||||
|
||||
evennia test --settings settings.py .world.tests.YourTest
|
||||
|
||||
|
||||
## Writing new unit tests
|
||||
|
||||
Evennia's test suite makes use of Django unit test system, which in turn relies on Python's
|
||||
*unittest* module.
|
||||
|
||||
To make the test runner find the tests, they must be put in a module named `test*.py` (so `test.py`,
|
||||
`tests.py` etc). Such a test module will be found wherever it is in the package. It can be a good
|
||||
idea to look at some of Evennia's `tests.py` modules to see how they look.
|
||||
|
||||
Inside the module you need to put a class inheriting (at any distance) from `unittest.TestCase`. Each
|
||||
method on that class that starts with `test_` will be run separately as a unit test. There
|
||||
are two special, optional methods `setUp` and `tearDown` that will (if you define them) run before
|
||||
_every_ test. This can be useful for setting up and deleting things.
|
||||
|
||||
To actually test things, you use special `assert...` methods on the class. Most common on is
|
||||
`assertEqual`, which makes sure a result is what you expect it to be.
|
||||
|
||||
Here's an example of the principle. Let's assume you put this in `mygame/world/tests.py`
|
||||
and want to test a function in `mygame/world/myfunctions.py`
|
||||
|
||||
```python
|
||||
# in a module tests.py somewhere i your game dir
|
||||
import unittest
|
||||
|
||||
from evennia import create_object
|
||||
# the function we want to test
|
||||
from .myfunctions import myfunc
|
||||
|
||||
|
||||
class TestObj(unittest.TestCase):
|
||||
"This tests a function myfunc."
|
||||
|
||||
def setUp(self):
|
||||
"""done before every of the test_ * methods below"""
|
||||
self.obj = create_object("mytestobject")
|
||||
|
||||
def tearDown(self):
|
||||
"""done after every test_* method below """
|
||||
self.obj.delete()
|
||||
|
||||
def test_return_value(self):
|
||||
"""test method. Makes sure return value is as expected."""
|
||||
actual_return = myfunc(self.obj)
|
||||
expected_return = "This is the good object 'mytestobject'."
|
||||
# test
|
||||
self.assertEqual(expected_return, actual_return)
|
||||
def test_alternative_call(self):
|
||||
"""test method. Calls with a keyword argument."""
|
||||
actual_return = myfunc(self.obj, bad=True)
|
||||
expected_return = "This is the baaad object 'mytestobject'."
|
||||
# test
|
||||
self.assertEqual(expected_return, actual_return)
|
||||
```
|
||||
|
||||
To test this, run
|
||||
|
||||
evennia test --settings settings.py .
|
||||
|
||||
to run the entire test module
|
||||
|
||||
evennia test --settings setings.py .world.tests
|
||||
|
||||
or a specific class:
|
||||
|
||||
evennia test --settings settings.py .world.tests.TestObj
|
||||
|
||||
You can also run a specific test:
|
||||
|
||||
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).
|
||||
|
||||
### Using the Evennia testing classes
|
||||
|
||||
Evennia offers many custom testing classes that helps with testing Evennia features.
|
||||
They are all found in [evennia.utils.test_resources](evennia.utils.test_resources). Note that
|
||||
these classes implement the `setUp` and `tearDown` already, so if you want to add stuff in them
|
||||
yourself you should remember to use e.g. `super().setUp()` in your code.
|
||||
|
||||
#### Classes for testing your game dir
|
||||
|
||||
These all use whatever setting you pass to them and works well for testing code in your game dir.
|
||||
|
||||
- `EvenniaTest` - this sets up a full object environment for your test. All the created entities
|
||||
can be accesses as properties on the class:
|
||||
- `.account` - A fake [Account](evennia.accounts.accounts.DefaultAccount) named "TestAccount".
|
||||
- `.account2` - Another account named "TestAccount2"
|
||||
- `char1` - A [Character](evennia.objects.objects.DefaultCharacter) linked to `.account`, named `Char`.
|
||||
This has 'Developer' permissions but is not a superuser.
|
||||
- `.char2` - Another character linked to `account`, named `Char2`. This has base permissions (player).
|
||||
- `.obj1` - A regular [Object](evennia.objects.objects.DefaultObject) named "Obj".
|
||||
- `.obj2` - Another object named "Obj2".
|
||||
- `.room1` - A [Room](evennia.objects.objects.DefaultRoom) named "Room". Both characters and both
|
||||
objects are located inside this room. It has a description of "room_desc".
|
||||
- `.room2` - Another room named "Room2". It is empty and has no set description.
|
||||
- `.exit` - An exit named "out" that leads from `.room1` to `.room2`.
|
||||
- `.script` - A [Script](evennia.scripts.scripts.DefaultScript) named "Script". It's an inert script
|
||||
without a timing component.
|
||||
- `.session` - A fake [Session](evennia.server.serversession.ServerSession) that mimics a player
|
||||
connecting to the game. It is used by `.account1` and has a sessid of 1.
|
||||
- `EvenniaCommandTest` - has the same environment like `EvenniaTest` but also adds a special
|
||||
[.call()](evennia.utils.test_resources.EvenniaCommandTestMixin.call) method specifically for
|
||||
testing Evennia [Commands](../Components/Commands.md). It allows you to compare what the command _actually_
|
||||
returns to the player with what you expect. Read the `call` api doc for more info.
|
||||
- `EvenniaTestCase` - This is identical to the regular Python `TestCase` class, it's
|
||||
just there for naming symmetry with `BaseEvenniaTestCase` below.
|
||||
|
||||
Here's an example of using `EvenniaTest`
|
||||
|
||||
```python
|
||||
# in a test module
|
||||
|
||||
from evennia.utils.test_resources import EvenniaTest
|
||||
|
||||
class TestObject(EvenniaTest):
|
||||
"""Remember that the testing class creates char1 and char2 inside room1 ..."""
|
||||
def test_object_search_character(self):
|
||||
"""Check that char1 can search for char2 by name"""
|
||||
self.assertEqual(self.char1.search(self.char2.key), self.char2)
|
||||
|
||||
def test_location_search(self):
|
||||
"""Check so that char1 can find the current location by name"""
|
||||
self.assertEqual(self.char1.search(self.char1.location.key), self.char1.location)
|
||||
# ...
|
||||
```
|
||||
|
||||
This example tests a custom command.
|
||||
|
||||
```python
|
||||
from evennia.commands.default.tests import EvenniaCommandTest
|
||||
from commands import command as mycommand
|
||||
|
||||
|
||||
class TestSet(EvenniaCommandTest):
|
||||
"tests the look command by simple call, using Char2 as a target"
|
||||
|
||||
def test_mycmd_char(self):
|
||||
self.call(mycommand.CmdMyLook(), "Char2", "Char2(#7)")
|
||||
|
||||
def test_mycmd_room(self):
|
||||
"tests the look command by simple call, with target as room"
|
||||
self.call(mycommand.CmdMyLook(), "Room",
|
||||
"Room(#1)\nroom_desc\nExits: out(#3)\n"
|
||||
"You see: Obj(#4), Obj2(#5), Char2(#7)")
|
||||
```
|
||||
|
||||
When using `.call`, you don't need to specify the entire string; you can just give the beginning
|
||||
of it and if it matches, that's enough. Use `\n` to denote line breaks and (this is a special for
|
||||
the `.call` helper), `||` to indicate multiple uses of `.msg()` in the Command. The `.call` helper
|
||||
has a lot of arguments for mimicing different ways of calling a Command, so make sure to
|
||||
[read the API docs for .call()](evennia.utils.test_resources.EvenniaCommandTestMixin.call).
|
||||
|
||||
#### Classes for testing Evennia core
|
||||
|
||||
These are used for testing Evennia itself. They provide the same resources as the classes
|
||||
above but enforce Evennias default settings found in `evennia/settings_default.py`, ignoring
|
||||
any settings changes in your game dir.
|
||||
|
||||
- `BaseEvenniaTest` - all the default objects above but with enforced default settings
|
||||
- `BaseEvenniaCommandTest` - for testing Commands, but with enforced default settings
|
||||
- `BaseEvenniaTestCase` - no default objects, only enforced default settings
|
||||
|
||||
There are also two special 'mixin' classes. These are uses in the classes above, but may also
|
||||
be useful if you want to mix your own testing classes:
|
||||
|
||||
- `EvenniaTestMixin` - A class mixin that creates all test environment objects.
|
||||
- `EvenniaCommandMixin` - A class mixin that adds the `.call()` Command-tester helper.
|
||||
|
||||
If you want to help out writing unittests for Evennia, take a look at Evennia's [coveralls.io
|
||||
page](https://coveralls.io/github/evennia/evennia). There you see which modules have any form of
|
||||
test coverage and which does not. All help is appreciated!
|
||||
|
||||
### Unit testing contribs with custom models
|
||||
|
||||
A special case is if you were to create a contribution to go to the `evennia/contrib` folder that
|
||||
uses its [own database models](../Concepts/Models.md). The problem with this is that Evennia (and Django) will
|
||||
only recognize models in `settings.INSTALLED_APPS`. If a user wants to use your contrib, they will
|
||||
be required to add your models to their settings file. But since contribs are optional you cannot
|
||||
add the model to Evennia's central `settings_default.py` file - this would always create your
|
||||
optional models regardless of if the user wants them. But at the same time a contribution is a part
|
||||
of the Evennia distribution and its unit tests should be run with all other Evennia tests using
|
||||
`evennia test evennia`.
|
||||
|
||||
The way to do this is to only temporarily add your models to the `INSTALLED_APPS` directory when the test runs. here is an example of how to do it.
|
||||
|
||||
> Note that this solution, derived from this [stackexchange answer](http://stackoverflow.com/questions/502916/django-how-to-create-a-model-dynamically-just-for-testing#503435) is currently untested! Please report your findings.
|
||||
|
||||
```python
|
||||
# a file contrib/mycontrib/tests.py
|
||||
|
||||
from django.conf import settings
|
||||
import django
|
||||
from evennia.utils.test_resources import BaseEvenniaTest
|
||||
|
||||
OLD_DEFAULT_SETTINGS = settings.INSTALLED_APPS
|
||||
DEFAULT_SETTINGS = dict(
|
||||
INSTALLED_APPS=(
|
||||
'contrib.mycontrib.tests',
|
||||
),
|
||||
DATABASES={
|
||||
"default": {
|
||||
"ENGINE": "django.db.backends.sqlite3"
|
||||
}
|
||||
},
|
||||
SILENCED_SYSTEM_CHECKS=["1_7.W001"],
|
||||
)
|
||||
|
||||
|
||||
class TestMyModel(BaseEvenniaTest):
|
||||
def setUp(self):
|
||||
if not settings.configured:
|
||||
settings.configure(**DEFAULT_SETTINGS)
|
||||
django.setup()
|
||||
|
||||
from django.core.management import call_command
|
||||
from django.db.models import loading
|
||||
loading.cache.loaded = False
|
||||
call_command('syncdb', verbosity=0)
|
||||
|
||||
def tearDown(self):
|
||||
settings.configure(**OLD_DEFAULT_SETTINGS)
|
||||
django.setup()
|
||||
|
||||
from django.core.management import call_command
|
||||
from django.db.models import loading
|
||||
loading.cache.loaded = False
|
||||
call_command('syncdb', verbosity=0)
|
||||
|
||||
# test cases below ...
|
||||
|
||||
def test_case(self):
|
||||
# test case here
|
||||
```
|
||||
|
||||
|
||||
### A note on making the test runner faster
|
||||
|
||||
If you have custom models with a large number of migrations, creating the test database can take a very long time. If you don't require migrations to run for your tests, you can disable them with the
|
||||
django-test-without-migrations package. To install it, simply:
|
||||
|
||||
```
|
||||
$ pip install django-test-without-migrations
|
||||
```
|
||||
|
||||
Then add it to your `INSTALLED_APPS` in your `server.conf.settings.py`:
|
||||
|
||||
```python
|
||||
INSTALLED_APPS = (
|
||||
# ...
|
||||
'test_without_migrations',
|
||||
)
|
||||
```
|
||||
|
||||
After doing so, you can then run tests without migrations by adding the `--nomigrations` argument:
|
||||
|
||||
```
|
||||
evennia test --settings settings.py --nomigrations .
|
||||
```
|
||||
344
docs/1.x/_sources/Coding/Version-Control.md.txt
Normal file
344
docs/1.x/_sources/Coding/Version-Control.md.txt
Normal file
|
|
@ -0,0 +1,344 @@
|
|||
# Coding using Version Control
|
||||
|
||||
[Version control](https://en.wikipedia.org/wiki/Version_control) allows you to track changes to your code. You can save 'snapshots' of your progress which means you can roll back undo things easily. Version control also allows you to easily back up your code to an online _repository_ such as Github. It also allows you to collaborate with others on the same code without clashing or worry about who changed what.
|
||||
|
||||
```{sidebar} Do it!
|
||||
It's _strongly_ recommended that you [put your game folder under version control](#putting-your-game-dir-under-version-control). Using git is is also the way to contribue to Evennia itself.
|
||||
```
|
||||
|
||||
Evennia uses the most commonly used version control system, [Git](https://git-scm.com/) . For additional help on using Git, please refer to the [Official GitHub documentation](https://help.github.com/articles/set-up-git#platform-all).
|
||||
|
||||
## Setting up Git
|
||||
|
||||
- **Fedora Linux**
|
||||
|
||||
yum install git-core
|
||||
|
||||
- **Debian Linux** _(Ubuntu, Linux Mint, etc.)_
|
||||
|
||||
apt-get install git
|
||||
|
||||
- **Windows**: It is recommended to use [Git for Windows](https://gitforwindows.org/).
|
||||
- **Mac**: Mac platforms offer two methods for installation, one via MacPorts, which you can find out about [here](https://git-scm.com/book/en/Getting-Started-Installing-Git#Installing-on-Mac), or you can use the [Git OSX Installer](https://sourceforge.net/projects/git-osx-installer/).
|
||||
|
||||
> You can find expanded instructions for installation [here](https://git-scm.com/book/en/Getting-Started-Installing-Git).
|
||||
|
||||
```{sidebar} Git user nickname
|
||||
If you ever make your code available online (or contribute to Evennia), your name will be visible to those reading the code-commit history. So if you are not comfortable with using your real, full name online, put a nickname (or your github handler) here.
|
||||
```
|
||||
To avoid a common issue later, you will need to set a couple of settings; first you will need to tell Git your username, followed by your e-mail address, so that when you commit code later you will be properly credited.
|
||||
|
||||
|
||||
1. Set the default name for git to use when you commit:
|
||||
|
||||
git config --global user.name "Your Name Here"
|
||||
|
||||
2. Set the default email for git to use when you commit:
|
||||
|
||||
git config --global user.email "your_email@example.com"
|
||||
|
||||
> To get a running start with Git, here's [a good YouTube talk about it](https://www.youtube.com/watch?v=1ffBJ4sVUb4#t=1m58s). It's a bit long but it will help you understand the underlying ideas behind GIT (which in turn makes it a lot more intuitive to use).
|
||||
|
||||
## Common Git commands
|
||||
|
||||
```{sidebar} Git repository
|
||||
This is just a fancy name for the folder you have designated to be under version control. We will make your `mygame` game folder into such a repository. The Evennia code is also in a (separate) git repository.
|
||||
```
|
||||
Git can be controlled via a GUI. But it's often easier to use the base terminal/console commands, since it makes it clear if something goes wrong.
|
||||
|
||||
All these actions need to be done from inside the _git repository_ .
|
||||
|
||||
Git may seem daunting at first. But when working with git, you'll be using the same 2-3 commands 99% of the time. And you can make git _aliases_ to have them be even easier to remember.
|
||||
|
||||
|
||||
### `git init`
|
||||
|
||||
This initializes a folder/directory on your drive as a 'git repository'
|
||||
|
||||
git init .
|
||||
|
||||
The `.` means to apply to the current directory. If you are inside `mygame`, this makes your game dir into a git repository. That's all there is to it, really. You only need to do this once.
|
||||
|
||||
### `git add`
|
||||
|
||||
git add <file>
|
||||
|
||||
This tells Git to start to _track_ the file under version control. You need to do this when you create a new file. You can also add all files in your current directory:
|
||||
|
||||
git add .
|
||||
|
||||
Or
|
||||
|
||||
git add *
|
||||
|
||||
All files in the current directory are now tracked by Git. You only need to do this once for every file you want to track.
|
||||
|
||||
### `git commit`
|
||||
|
||||
git commit -a -m "This is the initial commit"
|
||||
|
||||
This _commits_ your changes. It stores a snapshot of all (`-a`) your code at the current time, adding a message `-m` so you know what you did. Later you can _check out_ your code the way it was at a given time. The message is mandatory and you will thank yourself later if write clear and descriptive log messages. If you don't add `-m`, a text editor opens for you to write the message instead.
|
||||
|
||||
The `git commit` is something you'll be using all the time, so it can be useful to make a _git alias_ for it:
|
||||
|
||||
git config --global alias.cma 'commit -a -m'
|
||||
|
||||
After you've run this, you can commit much simpler, like this:
|
||||
|
||||
git cma "This is the initial commit"
|
||||
|
||||
Much easier to remember!
|
||||
|
||||
### `git status`, `git diff` and `git log`
|
||||
|
||||
|
||||
git status -s
|
||||
|
||||
This gives a short (`-s`) of the files that changes since your last `git commit`.
|
||||
|
||||
git diff --word-diff`
|
||||
|
||||
This shows exactly what changed in each file since you last made a `git commit`. The `--word-diff` option means it will mark if a single word changed on a line.
|
||||
|
||||
git log
|
||||
|
||||
This shows the log of all `commits` done. Each log will show you who made the change, the commit-message and a unique _hash_ (like `ba214f12ab12e123...`) that uniquely describes that commit.
|
||||
|
||||
You can make the `log` command more succinct with some more options:
|
||||
|
||||
ls=log --pretty=format:%C(green)%h\ %C(yellow)[%ad]%Cred%d\ %Creset%s%Cblue\ [%an] --decorate --date=relative
|
||||
|
||||
This adds coloration and another fancy effects (use `git help log` to see what they mean).
|
||||
|
||||
Let's add aliases:
|
||||
|
||||
git config --global alias.st 'status -s'
|
||||
git config --global alias.df 'diff --word-diff'
|
||||
git config --global alias.ls 'log --pretty=format:%C(green)%h\ %C(yellow)[%ad]%Cred%d\ %Creset%s%Cblue\ [%an] --decorate --date=relative'
|
||||
|
||||
You can now use the much shorter
|
||||
|
||||
git st # short status
|
||||
git dif # diff with word-marking
|
||||
git ls # log with pretty formatting
|
||||
|
||||
for these useful functions.
|
||||
|
||||
### `git branch`, `checkout` and `merge`
|
||||
|
||||
Git allows you to work with _branches_. These are separate development paths your code may take, completely separate from each other. You can later _merge_ the code from a branch back into another branch. Evennia's `main` and `develop` branches are examples of this.
|
||||
|
||||
git branch -b branchaname
|
||||
|
||||
This creates a new branch, exactly identical to the branch you were on. It also moves you to that branch.
|
||||
|
||||
git branch -D branchname
|
||||
|
||||
Deletes a branch.
|
||||
|
||||
git branch
|
||||
|
||||
Shows all your branches, marking which one you are currently on.
|
||||
|
||||
git checkout branchname
|
||||
|
||||
This checks out another branch. As long as you are in a branch all `git commit`s will commit the code to that branch only.
|
||||
|
||||
git checkout .
|
||||
|
||||
This checks out your _current branch_ and has the effect of throwing away all your changes since your last commit. This is like undoing what you did since the last save point.
|
||||
|
||||
git checkout b2342bc21c124
|
||||
|
||||
This checks out a particular _commit_, identified by the hash you find with `git log`. This open a 'temporary branch' where the code is as it was when you made this commit. As an example, you can use this to check where a bug was introduced. Check out an existing branch to go back to your normal timeline, or use `git branch -b newbranch` to break this code off into a new branch you can continue working from.
|
||||
|
||||
git merge branchname
|
||||
|
||||
This _merges_ the code from `branchname` into the branch you are currently in. Doing so may lead to _merge conflicts_ if the same code changed in different ways in the two branches. See [how to resolve merge conflicts in git](https://phoenixnap.com/kb/how-to-resolve-merge-conflicts-in-git) for more help.
|
||||
|
||||
### `git glone`, `git push` and `git pull`
|
||||
|
||||
All of these other commands have dealt with code only sitting in your local repository-folder. These commands instead allows you to exchange code with a _remote_ repository - usually one that is online (like on github).
|
||||
|
||||
> How you actually set up a remote repository is described [in the next section](#pushing-your-code-online).
|
||||
|
||||
git clone repository/path
|
||||
|
||||
This copies the remote repository to your current location. If you used the [Git installation instructions](../Setup/Installation-Git.md) to install Evennia, this is what you used to get your local copy of the Evennia repository.
|
||||
|
||||
git pull
|
||||
|
||||
Once you cloned or otherwise set up a remote repository, using `git pull` will re-sync the remote with what you have locally. If what you download clashes with local changes, git will force you to `git commit` your changes before you can continue with `git pull`.
|
||||
|
||||
git push
|
||||
|
||||
This uploads your local changes _of your current branch_ to the same-named branch on the remote repository. To be able to do this you must have write-permissions to the remote repository.
|
||||
|
||||
### Other git commands
|
||||
|
||||
There are _many_ other git commands. Read up on them online:
|
||||
|
||||
git reflog
|
||||
|
||||
Shows hashes of individual git actions. This allows you to go back in the git event history itself.
|
||||
|
||||
|
||||
git reset
|
||||
|
||||
Force reset a branch to an earlier commit. This could throw away some history, so be careful.
|
||||
|
||||
git grep -n -I -i <query>
|
||||
|
||||
Quickly search for a phrase/text in all files tracked by git. Very useful to quickly find where things are. Set up an alias `git gr` with
|
||||
|
||||
```
|
||||
git config --global alias.gr 'grep -n -I -i'
|
||||
```
|
||||
|
||||
## Putting your game dir under version control
|
||||
|
||||
This makes use of the git commands listed in the previous section.
|
||||
|
||||
```{sidebar} git aliases
|
||||
If you set up the git aliases for commands suggested in the previous section, you can use them instead!
|
||||
```
|
||||
|
||||
cd mygame
|
||||
git init .
|
||||
git add *
|
||||
git commit -a -m "Initial commit"
|
||||
|
||||
|
||||
Your game-dir is now tracked by git.
|
||||
|
||||
You will notice that some files are not covered by your git version control, notably your secret-settings file (`mygame/server/conf/secret_settings.py`) and your sqlite3 database file `mygame/server/evennia.db3`. This is intentional and controlled from the file `mygame/.gitignore`.
|
||||
|
||||
```{warning}
|
||||
You should *never* put your sqlite3 database file into git by removing its entry
|
||||
in `.gitignore`. GIT is for backing up your code, not your database. That way
|
||||
lies madness and a good chance you'll confuse yourself. Make one mistake or local change and after a few commits and reverts you will have lost track of what is in your database or not. If you want to backup your SQlite3 database, do so by simply copying the database file to a safe location.
|
||||
```
|
||||
|
||||
### Pushing your code online
|
||||
|
||||
So far your code is only located on your private machine. A good idea is to back it up online. The easiest way to do this is to `git push` it to your own remote repository on GitHub. So for this you need a (free) Github account.
|
||||
|
||||
If you don't want your code to be publicly visible, Github also allows you set up a _private_ repository, only visible to you.
|
||||
|
||||
Create a new, empty repository on Github. [Github explains how here](https://help.github.com/articles/create-a-repo/) . _Don't_ allow it to add a README, license etc, that will just clash with what we upload later.
|
||||
|
||||
```{sidebar} Origin
|
||||
We label the remote repository 'origin'. This is the git default and means we won't need to specify it explicitly later.
|
||||
```
|
||||
|
||||
Make sure you are in your local game dir (previously initialized as a git repo).
|
||||
|
||||
git remote add origin <github URL>
|
||||
|
||||
This tells Git that there is a remote repository at `<github URL>`. See the github docs as to which URL to use. Verify that the remote works with `git remote -v`
|
||||
|
||||
Now we push to the remote (labeled 'origin' which is the default):
|
||||
|
||||
git push
|
||||
|
||||
Depending on how you set up your authentication with github, you may be asked to enter your github username and password. If you set up SSH authentication, this command will just work.
|
||||
|
||||
You use `git push` to upload your local changes so the remote repository is in sync with your local one. If you edited a file online using the Github editor (or a collaborator pushed code), you use `git pull` to sync in the other direction.
|
||||
|
||||
## Contributing to Evennia
|
||||
|
||||
If you want to help contributing to Evennia you must do so by _forking_ - making your own remote copy of the Evennia repository on Github. So for this, you need a (free) Github account. Doing so is a completely separate process from [putting your game dir under version control](#putting-your-game-dir-under-version-control) (which you should also do!).
|
||||
|
||||
At the top right of [the evennia github page](https://github.com/evennia/evennia), click the "Fork" button:
|
||||
|
||||

|
||||
|
||||
This will create a new online fork Evennia under your github account.
|
||||
|
||||
The fork only exists online as of yet. In a terminal, `cd` to the folder you wish to develop in. This folder should _not_ be your game dir, nor the place you cloned Evennia into if you used the [Git installation](../Setup/Installation-Git.md).
|
||||
|
||||
From this directory run the following command:
|
||||
|
||||
git clone https://github.com/yourusername/evennia.git evennia
|
||||
|
||||
This will download your fork to your computer. It creates a new folder `evennia/` at your current location. If you installed Evennia using the [Git installation](../Setup/Installation-Git.md), this folder will be identical in content to the `evennia` folder you cloned during that installation. The difference is that this repo is connected to your remote fork and not to the 'original' _upstream_ Evennia.
|
||||
|
||||
When we cloned our fork, git automatically set up a 'remote repository' labeled `origin` pointing to it. So if we do `git pull` and `git push`, we'll push to our fork.
|
||||
|
||||
We now want to add a second remote repository linked to the original Evennia repo. We will label this remote repository `upstream`:
|
||||
|
||||
cd evennia
|
||||
git remote add upstream https://github.com/evennia/evennia.git
|
||||
|
||||
If you also want to access Evennia's `develop` branch (the bleeding edge development) do the following:
|
||||
|
||||
git fetch upstream develop
|
||||
git checkout develop
|
||||
|
||||
Use
|
||||
|
||||
git checkout main
|
||||
git checkout develop
|
||||
|
||||
to switch between the branches.
|
||||
|
||||
To pull the latest from upstream Evennia, just checkout the branch you want and do
|
||||
|
||||
git pull upstream
|
||||
|
||||
```{sidebar} Pushing to upstream
|
||||
You can't do `git push upstream` unless you have write-access to the upstream Evennia repository. So there is no risk of you accidentally pushing your own code into the main, public repository.
|
||||
```
|
||||
|
||||
### Fixing an Evennia bug or feature
|
||||
|
||||
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 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.
|
||||
|
||||
Upstream Evennia is not standing still, so you want to make sure that your work is up-to-date with upstream changes. Make sure to first commit your `myfixbranch` changes, then
|
||||
|
||||
git checkout main (or develop)
|
||||
git pull upstream
|
||||
git checkout myfixbranch
|
||||
git merge main (or develop)
|
||||
|
||||
Up to this point your `myfixbranch` branch only exists on your local computer. No
|
||||
one else can see it.
|
||||
|
||||
git push
|
||||
|
||||
This will automatically create a matching `myfixbranch` in your forked version of Evennia and push to it. On github you will be able to see appear it in the `branches` dropdown. You can keep pushing to your remote `myfixbranch` as much as you like.
|
||||
|
||||
Once you feel you have something to share, you need to [create a pull request](https://github.com/evennia/evennia/pulls) (PR):
|
||||
This is a formal request for upstream Evennia to adopt and pull your code into the main repository.
|
||||
1. Click `New pull request`
|
||||
2. Choose `compare across forks`
|
||||
3. Select your fork from dropdown list of `head repository` repos. Pick the right branch to `compare`.
|
||||
4. On the Evennia side (to the left) make sure to pick the right `base` branch: If you want to contribute a change to the `develop` branch, you must pick `develop` as the `base`.
|
||||
5. Then click `Create pull request` and fill in as much information as you can in the form.
|
||||
6. Optional: Once you saved your PR, you can go into your code (on github) and add some per-line comments; this can help reviewers by explaining complex code or decisions you made.
|
||||
|
||||
Now you just need to wait for your code to be reviewed. Expect to get feedback and be asked to make changes, add more documentation etc. Getting as PR merged can take a few iterations.
|
||||
|
||||
```{sidebar} Not all PRs can merge
|
||||
While most PRs get merged, Evennia can't **guarantee** that your PR code will be deemed suitable to merge into upstream Evennia. For this reason it's a good idea to check in with the community _before_ you spend a lot of time on a large piece of code (fixing bugs is always a safe bet though!)
|
||||
```
|
||||
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Getting 403: Forbidden access
|
||||
|
||||
Some users have experienced this on `git push` to their remote repository. They are not asked for username/password (and don't have a ssh key set up).
|
||||
|
||||
Some users have reported that the workaround is to create a file `.netrc` under your home directory and add your github credentials there:
|
||||
|
||||
```bash
|
||||
machine github.com
|
||||
login <my_github_username>
|
||||
password <my_github_password>
|
||||
```
|
||||
Loading…
Add table
Add a link
Reference in a new issue