Tick #1 - Timmy: Timmy stands at The Threshold, watching the world. | Bezalel: Bezalel tests the Forge. The hearth still glows.

This commit is contained in:
Alexander Whitestone
2026-04-05 23:02:25 -04:00
parent e99e753c5c
commit 39a76f0adc
202 changed files with 14775 additions and 237 deletions

View File

@@ -0,0 +1,38 @@
# server/
This directory holds files used by and configuring the Evennia server
itself.
Out of all the subdirectories in the game directory, Evennia does
expect this directory to exist, so you should normally not delete,
rename or change its folder structure.
When running you will find four new files appear in this directory:
- `server.pid` and `portal.pid`: These hold the process IDs of the
Portal and Server, so that they can be managed by the launcher. If
Evennia is shut down uncleanly (e.g. by a crash or via a kill
signal), these files might erroneously remain behind. If so Evennia
will tell you they are "stale" and they can be deleted manually.
- `server.restart` and `portal.restart`: These hold flags to tell the
server processes if it should die or start again. You never need to
modify those files.
- `evennia.db3`: This will only appear if you are using the default
SQLite3 database; it a binary file that holds the entire game
database; deleting this file will effectively reset the game for
you and you can start fresh with `evennia migrate` (useful during
development).
## server/conf/
This subdirectory holds the configuration modules for the server. With
them you can change how Evennia operates and also plug in your own
functionality to replace the default. You usually need to restart the
server to apply changes done here. The most important file is the file
`settings.py` which is the main configuration file of Evennia.
## server/logs/
This subdirectory holds various log files created by the running
Evennia server. It is also the default location for storing any custom
log files you might want to output using Evennia's logging mechanisms.

View File

@@ -0,0 +1 @@
# -*- coding: utf-8 -*-

View File

@@ -0,0 +1 @@
# -*- coding: utf-8 -*-

View File

@@ -0,0 +1,19 @@
"""
At_initial_setup module template
Custom at_initial_setup method. This allows you to hook special
modifications to the initial server startup process. Note that this
will only be run once - when the server starts up for the very first
time! It is called last in the startup process and can thus be used to
overload things that happened before it.
The module must contain a global function at_initial_setup(). This
will be called without arguments. Note that tracebacks in this module
will be QUIETLY ignored, so make sure to check it well to make sure it
does what you expect it to.
"""
def at_initial_setup():
pass

View File

@@ -0,0 +1,54 @@
"""
Search and multimatch handling
This module allows for overloading two functions used by Evennia's
search functionality:
at_search_result:
This is called whenever a result is returned from an object
search (a common operation in commands). It should (together
with at_multimatch_input below) define some way to present and
differentiate between multiple matches (by default these are
presented as 1-ball, 2-ball etc)
at_multimatch_input:
This is called with a search term and should be able to
identify if the user wants to separate a multimatch-result
(such as that from a previous search). By default, this
function understands input on the form 1-ball, 2-ball etc as
indicating that the 1st or 2nd match for "ball" should be
used.
This module is not called by default, to use it, add the following
line to your settings file:
SEARCH_AT_RESULT = "server.conf.at_search.at_search_result"
"""
def at_search_result(matches, caller, query="", quiet=False, **kwargs):
"""
This is a generic hook for handling all processing of a search
result, including error reporting.
Args:
matches (list): This is a list of 0, 1 or more typeclass instances,
the matched result of the search. If 0, a nomatch error should
be echoed, and if >1, multimatch errors should be given. Only
if a single match should the result pass through.
caller (Object): The object performing the search and/or which should
receive error messages.
query (str, optional): The search query used to produce `matches`.
quiet (bool, optional): If `True`, no messages will be echoed to caller
on errors.
Keyword Args:
nofound_string (str): Replacement string to echo on a notfound error.
multimatch_string (str): Replacement string to echo on a multimatch error.
Returns:
processed_result (Object or None): This is always a single result
or `None`. If `None`, any error reporting/handling should
already have happened.
"""

View File

@@ -0,0 +1,71 @@
"""
Server startstop hooks
This module contains functions called by Evennia at various
points during its startup, reload and shutdown sequence. It
allows for customizing the server operation as desired.
This module must contain at least these global functions:
at_server_init()
at_server_start()
at_server_stop()
at_server_reload_start()
at_server_reload_stop()
at_server_cold_start()
at_server_cold_stop()
"""
def at_server_init():
"""
This is called first as the server is starting up, regardless of how.
"""
pass
def at_server_start():
"""
This is called every time the server starts up, regardless of
how it was shut down.
"""
pass
def at_server_stop():
"""
This is called just before the server is shut down, regardless
of it is for a reload, reset or shutdown.
"""
pass
def at_server_reload_start():
"""
This is called only when server starts back up after a reload.
"""
pass
def at_server_reload_stop():
"""
This is called only time the server stops before a reload.
"""
pass
def at_server_cold_start():
"""
This is called only when the server starts "cold", i.e. after a
shutdown or a reset.
"""
pass
def at_server_cold_stop():
"""
This is called only when the server goes down due to a shutdown or
reset.
"""
pass

View File

@@ -0,0 +1,55 @@
"""
Changing the default command parser
The cmdparser is responsible for parsing the raw text inserted by the
user, identifying which command/commands match and return one or more
matching command objects. It is called by Evennia's cmdhandler and
must accept input and return results on the same form. The default
handler is very generic so you usually don't need to overload this
unless you have very exotic parsing needs; advanced parsing is best
done at the Command.parse level.
The default cmdparser understands the following command combinations
(where [] marks optional parts.)
[cmdname[ cmdname2 cmdname3 ...] [the rest]
A command may consist of any number of space-separated words of any
length, and contain any character. It may also be empty.
The parser makes use of the cmdset to find command candidates. The
parser return a list of matches. Each match is a tuple with its first
three elements being the parsed cmdname (lower case), the remaining
arguments, and the matched cmdobject from the cmdset.
This module is not accessed by default. To tell Evennia to use it
instead of the default command parser, add the following line to
your settings file:
COMMAND_PARSER = "server.conf.cmdparser.cmdparser"
"""
def cmdparser(raw_string, cmdset, caller, match_index=None):
"""
This function is called by the cmdhandler once it has
gathered and merged all valid cmdsets valid for this particular parsing.
raw_string - the unparsed text entered by the caller.
cmdset - the merged, currently valid cmdset
caller - the caller triggering this parsing
match_index - an optional integer index to pick a given match in a
list of same-named command matches.
Returns:
list of tuples: [(cmdname, args, cmdobj, cmdlen, mratio), ...]
where cmdname is the matching command name and args is
everything not included in the cmdname. Cmdobj is the actual
command instance taken from the cmdset, cmdlen is the length
of the command name and the mratio is some quality value to
(possibly) separate multiple matches.
"""
# Your implementation here

View File

@@ -0,0 +1,40 @@
# -*- coding: utf-8 -*-
"""
Connection screen
This is the text to show the user when they first connect to the game (before
they log in).
To change the login screen in this module, do one of the following:
- Define a function `connection_screen()`, taking no arguments. This will be
called first and must return the full string to act as the connection screen.
This can be used to produce more dynamic screens.
- Alternatively, define a string variable in the outermost scope of this module
with the connection string that should be displayed. If more than one such
variable is given, Evennia will pick one of them at random.
The commands available to the user when the connection screen is shown
are defined in evennia.default_cmds.UnloggedinCmdSet. The parsing and display
of the screen is done by the unlogged-in "look" command.
"""
from django.conf import settings
from evennia import utils
CONNECTION_SCREEN = """
|b==============================================================|n
Welcome to |g{}|n, version {}!
If you have an existing account, connect to it by typing:
|wconnect <username> <password>|n
If you need to create an account, type (without the <>'s):
|wcreate <username> <password>|n
If you have spaces in your username, enclose it in quotes.
Enter |whelp|n for more info. |wlook|n will re-show this screen.
|b==============================================================|n""".format(
settings.SERVERNAME, utils.get_evennia_version("short")
)

View File

@@ -0,0 +1,39 @@
"""
Outgoing callables to apply with the FuncParser on outgoing messages.
The functions in this module will become available as $funcname(args, kwargs)
in all outgoing strings if you add
FUNCPARSER_PARSE_OUTGOING_MESSAGES_ENABLED = True
to your settings file. The default inlinefuncs are found at the bottom of
`evennia.utils.funcparser`.
In text, usage is straightforward:
$funcname(arg1, arg2, ..., key=val, key2=val2, ...)
Example 1 (using the "pad" inlinefunc):
say This is $pad("a center-padded text", 50,c,-) of width 50.
->
John says, "This is -------------- a center-padded text--------------- of width 50."
Example 2 (using nested "pad" and "time" inlinefuncs):
say The time is $pad($time(), 30)right now.
->
John says, "The time is Oct 25, 11:09 right now."
To add more inline functions, add them to this module, using
the following call signature:
def funcname(*args, **kwargs)
...
"""
# def capitalize(*args, **kwargs):
# "Silly capitalize example. Used as $capitalize
# if not args:
# return ''
# session = kwargs.get("session")
# return args[0].capitalize()

View File

@@ -0,0 +1,52 @@
"""
Input functions
Input functions are always called from the client (they handle server
input, hence the name).
This module is loaded by being included in the
`settings.INPUT_FUNC_MODULES` tuple.
All *global functions* included in this module are considered
input-handler functions and can be called by the client to handle
input.
An input function must have the following call signature:
cmdname(session, *args, **kwargs)
Where session will be the active session and *args, **kwargs are extra
incoming arguments and keyword properties.
A special command is the "default" command, which is will be called
when no other cmdname matches. It also receives the non-found cmdname
as argument.
default(session, cmdname, *args, **kwargs)
"""
# def oob_echo(session, *args, **kwargs):
# """
# Example echo function. Echoes args, kwargs sent to it.
#
# Args:
# session (Session): The Session to receive the echo.
# args (list of str): Echo text.
# kwargs (dict of str, optional): Keyed echo text
#
# """
# session.msg(oob=("echo", args, kwargs))
#
#
# def default(session, cmdname, *args, **kwargs):
# """
# Handles commands without a matching inputhandler func.
#
# Args:
# session (Session): The active Session.
# cmdname (str): The (unmatched) command name
# args, kwargs (any): Arguments to function.
#
# """
# pass

View File

@@ -0,0 +1,30 @@
"""
Lockfuncs
Lock functions are functions available when defining lock strings,
which in turn limits access to various game systems.
All functions defined globally in this module are assumed to be
available for use in lockstrings to determine access. See the
Evennia documentation for more info on locks.
A lock function is always called with two arguments, accessing_obj and
accessed_obj, followed by any number of arguments. All possible
arguments should be handled with *args, **kwargs. The lock function
should handle all eventual tracebacks by logging the error and
returning False.
Lock functions in this module extend (and will overload same-named)
lock functions from evennia.locks.lockfuncs.
"""
# def myfalse(accessing_obj, accessed_obj, *args, **kwargs):
# """
# called in lockstring with myfalse().
# A simple logger that always returns false. Prints to stdout
# for simplicity, should use utils.logger for real operation.
# """
# print "%s tried to access %s. Access denied." % (accessing_obj, accessed_obj)
# return False

View File

@@ -0,0 +1,105 @@
"""
MSSP (Mud Server Status Protocol) meta information
Modify this file to specify what MUD listing sites will report about your game.
All fields are static. The number of currently active players and your game's
current uptime will be added automatically by Evennia.
You don't have to fill in everything (and most fields are not shown/used by all
crawlers anyway); leave the default if so needed. You need to reload the server
before the updated information is made available to crawlers (reloading does
not affect uptime).
After changing the values in this file, you must register your game with the
MUD website list you want to track you. The listing crawler will then regularly
connect to your server to get the latest info. No further configuration is
needed on the Evennia side.
"""
MSSPTable = {
# Required fields
"NAME": "Mygame", # usually the same as SERVERNAME
# Generic
"CRAWL DELAY": "-1", # limit how often crawler may update the listing. -1 for no limit
"HOSTNAME": "", # telnet hostname
"PORT": ["4000"], # telnet port - most important port should be *last* in list!
"CODEBASE": "Evennia",
"CONTACT": "", # email for contacting the mud
"CREATED": "", # year MUD was created
"ICON": "", # url to icon 32x32 or larger; <32kb.
"IP": "", # current or new IP address
"LANGUAGE": "", # name of language used, e.g. English
"LOCATION": "", # full English name of server country
"MINIMUM AGE": "0", # set to 0 if not applicable
"WEBSITE": "", # http:// address to your game website
# Categorisation
"FAMILY": "Evennia",
"GENRE": "None", # Adult, Fantasy, Historical, Horror, Modern, None, or Science Fiction
# Gameplay: Adventure, Educational, Hack and Slash, None,
# Player versus Player, Player versus Environment,
# Roleplaying, Simulation, Social or Strategy
"GAMEPLAY": "",
"STATUS": "Open Beta", # Allowed: Alpha, Closed Beta, Open Beta, Live
"GAMESYSTEM": "Custom", # D&D, d20 System, World of Darkness, etc. Use Custom if homebrew
# Subgenre: LASG, Medieval Fantasy, World War II, Frankenstein,
# Cyberpunk, Dragonlance, etc. Or None if not applicable.
"SUBGENRE": "None",
# World
"AREAS": "0",
"HELPFILES": "0",
"MOBILES": "0",
"OBJECTS": "0",
"ROOMS": "0", # use 0 if room-less
"CLASSES": "0", # use 0 if class-less
"LEVELS": "0", # use 0 if level-less
"RACES": "0", # use 0 if race-less
"SKILLS": "0", # use 0 if skill-less
# Protocols set to 1 or 0; should usually not be changed)
"ANSI": "1",
"GMCP": "1",
"MSDP": "1",
"MXP": "1",
"SSL": "1",
"UTF-8": "1",
"MCCP": "1",
"XTERM 256 COLORS": "1",
"XTERM TRUE COLORS": "0",
"ATCP": "0",
"MCP": "0",
"MSP": "0",
"VT100": "0",
"PUEBLO": "0",
"ZMP": "0",
# Commercial set to 1 or 0)
"PAY TO PLAY": "0",
"PAY FOR PERKS": "0",
# Hiring set to 1 or 0)
"HIRING BUILDERS": "0",
"HIRING CODERS": "0",
# Extended variables
# World
"DBSIZE": "0",
"EXITS": "0",
"EXTRA DESCRIPTIONS": "0",
"MUDPROGS": "0",
"MUDTRIGS": "0",
"RESETS": "0",
# Game (set to 1 or 0, or one of the given alternatives)
"ADULT MATERIAL": "0",
"MULTICLASSING": "0",
"NEWBIE FRIENDLY": "0",
"PLAYER CITIES": "0",
"PLAYER CLANS": "0",
"PLAYER CRAFTING": "0",
"PLAYER GUILDS": "0",
"EQUIPMENT SYSTEM": "None", # "None", "Level", "Skill", "Both"
"MULTIPLAYING": "None", # "None", "Restricted", "Full"
"PLAYERKILLING": "None", # "None", "Restricted", "Full"
"QUEST SYSTEM": "None", # "None", "Immortal Run", "Automated", "Integrated"
"ROLEPLAYING": "None", # "None", "Accepted", "Encouraged", "Enforced"
"TRAINING SYSTEM": "None", # "None", "Level", "Skill", "Both"
# World originality: "All Stock", "Mostly Stock", "Mostly Original", "All Original"
"WORLD ORIGINALITY": "All Original",
}

View File

@@ -0,0 +1,24 @@
"""
Start plugin services
This plugin module can define user-created services for the Portal to
start.
This module must handle all imports and setups required to start
twisted services (see examples in evennia.server.portal.portal). It
must also contain a function start_plugin_services(application).
Evennia will call this function with the main Portal application (so
your services can be added to it). The function should not return
anything. Plugin services are started last in the Portal startup
process.
"""
def start_plugin_services(portal):
"""
This hook is called by Evennia, last in the Portal startup process.
portal - a reference to the main portal application.
"""
pass

View File

@@ -0,0 +1,24 @@
"""
Server plugin services
This plugin module can define user-created services for the Server to
start.
This module must handle all imports and setups required to start a
twisted service (see examples in evennia.server.server). It must also
contain a function start_plugin_services(application). Evennia will
call this function with the main Server application (so your services
can be added to it). The function should not return anything. Plugin
services are started last in the Server startup process.
"""
def start_plugin_services(server):
"""
This hook is called by Evennia, last in the Server startup process.
server - a reference to the main server application.
"""
pass

View File

@@ -0,0 +1,37 @@
"""
ServerSession
The serversession is the Server-side in-memory representation of a
user connecting to the game. Evennia manages one Session per
connection to the game. So a user logged into the game with multiple
clients (if Evennia is configured to allow that) will have multiple
sessions tied to one Account object. All communication between Evennia
and the real-world user goes through the Session(s) associated with that user.
It should be noted that modifying the Session object is not usually
necessary except for the most custom and exotic designs - and even
then it might be enough to just add custom session-level commands to
the SessionCmdSet instead.
This module is not normally called. To tell Evennia to use the class
in this module instead of the default one, add the following to your
settings file:
SERVER_SESSION_CLASS = "server.conf.serversession.ServerSession"
"""
from evennia.server.serversession import ServerSession as BaseServerSession
class ServerSession(BaseServerSession):
"""
This class represents a player's session and is a template for
individual protocols to communicate with Evennia.
Each account gets one or more sessions assigned to them whenever they connect
to the game server. All communication between game and account goes
through their session(s).
"""
pass

View File

@@ -0,0 +1,44 @@
r"""
Evennia settings file.
The available options are found in the default settings file found
here:
https://www.evennia.com/docs/latest/Setup/Settings-Default.html
Remember:
Don't copy more from the default file than you actually intend to
change; this will make sure that you don't overload upstream updates
unnecessarily.
When changing a setting requiring a file system path (like
path/to/actual/file.py), use GAME_DIR and EVENNIA_DIR to reference
your game folder and the Evennia library folders respectively. Python
paths (path.to.module) should be given relative to the game's root
folder (typeclasses.foo) whereas paths within the Evennia library
needs to be given explicitly (evennia.foo).
If you want to share your game dir, including its settings, you can
put secret game- or server-specific settings in secret_settings.py.
"""
# Use the defaults from Evennia unless explicitly overridden
from evennia.settings_default import *
######################################################################
# Evennia base server config
######################################################################
# This is the name of your game. Make it catchy!
SERVERNAME = "tower-world"
######################################################################
# Settings given in secret_settings.py override those in this file.
######################################################################
try:
from server.conf.secret_settings import *
except ImportError:
print("secret_settings.py file not found or failed to import.")

View File

@@ -0,0 +1,41 @@
"""
Web plugin hooks.
"""
def at_webserver_root_creation(web_root):
"""
This is called as the web server has finished building its default
path tree. At this point, the media/ and static/ URIs have already
been added to the web root.
Args:
web_root (twisted.web.resource.Resource): The root
resource of the URI tree. Use .putChild() to
add new subdomains to the tree.
Returns:
web_root (twisted.web.resource.Resource): The potentially
modified root structure.
Example:
from twisted.web import static
my_page = static.File("web/mypage/")
my_page.indexNames = ["index.html"]
web_root.putChild("mypage", my_page)
"""
return web_root
def at_webproxy_root_creation(web_root):
"""
This function can modify the portal proxy service.
Args:
web_root (evennia.server.webserver.Website): The Evennia
Website application. Use .putChild() to add new
subdomains that are Portal-accessible over TCP;
primarily for new protocol development, but suitable
for other shenanigans.
"""
return web_root