Mayor first overhaul of the evennia.py launcher. Not tested yet.
This commit is contained in:
parent
84483b7842
commit
2846e64833
1 changed files with 360 additions and 270 deletions
630
game/evennia.py
630
game/evennia.py
|
|
@ -8,71 +8,70 @@ Sets the appropriate environmental variables and launches the server
|
||||||
and portal through the runner. Run without arguments to get a
|
and portal through the runner. Run without arguments to get a
|
||||||
menu. Run the script with the -h flag to see usage information.
|
menu. Run the script with the -h flag to see usage information.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
|
||||||
|
evennia init <path> - creates a new game location, sets up a custom
|
||||||
|
settings file and copies all templates to <path>
|
||||||
|
evennia [settings][options] - handles server start/stop/restart if called
|
||||||
|
from the game folder. Can be called outside
|
||||||
|
the game folder if called with the path
|
||||||
|
to the settings file.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import signal
|
import signal
|
||||||
from optparse import OptionParser
|
import shutil
|
||||||
from subprocess import Popen
|
import importlib
|
||||||
import django
|
import django
|
||||||
|
from argparse import ArgumentParser
|
||||||
# Set the Python path up so we can get to settings.py from here.
|
from subprocess import Popen
|
||||||
from django.core import management
|
from django.core import management
|
||||||
|
|
||||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
# Signal processing
|
||||||
|
SIG = signal.SIGINT
|
||||||
|
|
||||||
# Check/Create settings
|
# Set up the main python paths to Evennia
|
||||||
|
EVENNIA_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
EVENNIA_BIN = os.path.join(EVENNIA_ROOT, "bin")
|
||||||
|
EVENNIA_LIB = os.path.join(EVENNIA_ROOT, "lib")
|
||||||
|
EVENNIA_RUNNER = os.path.join(EVENNIA_BIN, "runner.py")
|
||||||
|
EVENNIA_TEMPLATE = os.path.join(EVENNIA_ROOT, "game_template")
|
||||||
|
|
||||||
_CREATED_SETTINGS = False
|
EVENNIA_VERSION = "Unknown"
|
||||||
if not os.path.exists('settings.py'):
|
TWISTED_BINARY = "twistd"
|
||||||
# If settings.py doesn't already exist, create it and populate it with some
|
|
||||||
# basic stuff.
|
|
||||||
|
|
||||||
# make random secret_key.
|
# Game directory structure
|
||||||
import random
|
SETTINGFILE = "settings.py"
|
||||||
import string
|
SERVERDIR = "server"
|
||||||
secret_key = list((string.letters +
|
CONFDIR = os.path.join(SERVERDIR, "conf")
|
||||||
string.digits + string.punctuation).replace("\\", "").replace("'", '"'))
|
SETTINGS_PATH = os.path.join(CONFDIR, SETTINGFILE)
|
||||||
random.shuffle(secret_key)
|
SETTINGS_DOTPATH = "server.conf.settings"
|
||||||
secret_key = "".join(secret_key[:40])
|
CURRENT_DIR = os.getcwd()
|
||||||
|
GAMEDIR = CURRENT_DIR
|
||||||
|
|
||||||
settings_file = open('settings.py', 'w')
|
# Operational setup
|
||||||
_CREATED_SETTINGS = True
|
SERVER_LOGFILE = None
|
||||||
|
PORTAL_LOGFILE = None
|
||||||
|
SERVER_PIDFILE = None
|
||||||
|
PORTAL_PIDFILE = None
|
||||||
|
SERVER_RESTART = None
|
||||||
|
PORTAL_RESTART = None
|
||||||
|
SERVER_PY_FILE = None
|
||||||
|
PORTAL_PY_FILE = None
|
||||||
|
|
||||||
string = \
|
# add Evennia root and bin dir to PYTHONPATH
|
||||||
|
sys.path.insert(0, EVENNIA_ROOT)
|
||||||
|
|
||||||
|
|
||||||
|
#------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Messages
|
||||||
|
#
|
||||||
|
#------------------------------------------------------------
|
||||||
|
|
||||||
|
WELCOME_MESSAGE = \
|
||||||
"""
|
"""
|
||||||
######################################################################
|
|
||||||
# Evennia MU* server configuration file
|
|
||||||
#
|
|
||||||
# You may customize your setup by copy&pasting the variables you want
|
|
||||||
# to change from the master config file src/settings_default.py to
|
|
||||||
# this file. Try to *only* copy over things you really need to customize
|
|
||||||
# and do *not* make any changes to src/settings_default.py directly.
|
|
||||||
# This way you'll always have a sane default to fall back on
|
|
||||||
# (also, the master config file may change with server updates).
|
|
||||||
#
|
|
||||||
######################################################################
|
|
||||||
|
|
||||||
from src.settings_default import *
|
|
||||||
|
|
||||||
######################################################################
|
|
||||||
# Custom settings
|
|
||||||
######################################################################
|
|
||||||
|
|
||||||
|
|
||||||
######################################################################
|
|
||||||
# SECRET_KEY was randomly seeded when settings.py was first created.
|
|
||||||
# Don't share this with anybody. It is used by Evennia to handle
|
|
||||||
# cryptographic hashing for things like cookies on the web side.
|
|
||||||
######################################################################
|
|
||||||
SECRET_KEY = '%s'
|
|
||||||
|
|
||||||
""" % secret_key
|
|
||||||
|
|
||||||
settings_file.write(string)
|
|
||||||
settings_file.close()
|
|
||||||
|
|
||||||
print """
|
|
||||||
Welcome to Evennia!
|
Welcome to Evennia!
|
||||||
|
|
||||||
No previous setting file was found so we created a fresh
|
No previous setting file was found so we created a fresh
|
||||||
|
|
@ -87,81 +86,101 @@ SECRET_KEY = '%s'
|
||||||
Make sure to create a superuser when asked. The superuser's
|
Make sure to create a superuser when asked. The superuser's
|
||||||
email-address does not have to exist.
|
email-address does not have to exist.
|
||||||
"""
|
"""
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
#------------------------------------------------------------
|
WARNING_RUNSERVER = \
|
||||||
# Test the import of the settings file
|
"""
|
||||||
#------------------------------------------------------------
|
WARNING: There is no need to run the Django development
|
||||||
try:
|
webserver to test out Evennia web features (the web client
|
||||||
from game import settings
|
will in fact not work since the Django test server knows
|
||||||
except Exception:
|
nothing about MUDs). Instead, just start Evennia with the
|
||||||
import traceback
|
webserver component active (this is the default).
|
||||||
string = "\n" + traceback.format_exc()
|
"""
|
||||||
|
|
||||||
# note - if this fails, ugettext will also fail, so we cannot translate this string.
|
ERROR_SETTINGS = \
|
||||||
|
"""
|
||||||
string += """\n
|
ERROR: Could not import the file {settingsfile} from {settingspath}.
|
||||||
Error: Couldn't import the file 'settings.py' in the directory containing %(file)r.
|
|
||||||
There are usually two reasons for this:
|
There are usually two reasons for this:
|
||||||
1) The settings module contains errors. Review the traceback above to resolve the
|
1) The settings file is a normal Python module. It may contain a syntax error.
|
||||||
problem, then try again.
|
Resolve the problem and try again.
|
||||||
2) If you get errors on finding DJANGO_SETTINGS_MODULE you might have set up django
|
2) Django is not correctly installed. This usually shows by errors involving
|
||||||
wrong in some way. If you run a virtual machine, it might be worth to restart it
|
'DJANGO_SETTINGS_MODULE'. If you run a virtual machine, it might be worth to restart it
|
||||||
to see if this resolves the issue. Evennia should not require you to define any
|
to see if this resolves the issue.
|
||||||
environment variables manually.
|
""".format(settingsfile=SETTINGFILE, settingspath=SETTINGS_PATH)
|
||||||
""" % {'file': __file__}
|
|
||||||
print string
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
# set the settings location
|
ERROR_DATABASE = \
|
||||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'game.settings'
|
"""
|
||||||
|
Your database does not seem to be set up correctly.
|
||||||
|
(error was '{traceback}')
|
||||||
|
|
||||||
# required since django1.7.
|
Try to run
|
||||||
django.setup()
|
|
||||||
|
|
||||||
# signal processing
|
python evennia.py
|
||||||
SIG = signal.SIGINT
|
|
||||||
|
|
||||||
|
to initialize the database according to your settings.
|
||||||
|
"""
|
||||||
|
|
||||||
|
ERROR_WINDOWS_WIN32API = \
|
||||||
|
"""
|
||||||
|
ERROR: Unable to import win32api, which Twisted requires to run.
|
||||||
|
You may download it from:
|
||||||
|
|
||||||
|
http://sourceforge.net/projects/pywin32
|
||||||
|
or
|
||||||
|
http://starship.python.net/crew/mhammond/win32/Downloads.html
|
||||||
|
"""
|
||||||
|
|
||||||
|
INFO_WINDOWS_BATFILE = \
|
||||||
|
"""
|
||||||
|
INFO: Since you are running Windows, a file 'twistd.bat' was
|
||||||
|
created for you. This is a simple batch file that tries to call
|
||||||
|
the twisted executable. Evennia determined this to be:
|
||||||
|
|
||||||
|
%(twistd_path)s
|
||||||
|
|
||||||
|
If you run into errors at startup you might need to edit
|
||||||
|
twistd.bat to point to the actual location of the Twisted
|
||||||
|
executable (usually called twistd.py) on your machine.
|
||||||
|
|
||||||
|
This procedure is only done once. Run evennia.py again when you
|
||||||
|
are ready to start the server.
|
||||||
|
"""
|
||||||
|
|
||||||
CMDLINE_HELP = \
|
CMDLINE_HELP = \
|
||||||
"""
|
"""
|
||||||
Main Evennia launcher. When starting in interactive (-i) mode, only
|
Main Evennia launcher. When starting in interactive (-i) mode, only
|
||||||
the Server will do so since this is the most commonly useful setup. To
|
the Server will do so since this is the most commonly useful setup. To
|
||||||
activate interactive mode also for the Portal, use the menu or launch
|
activate interactive mode also for the Portal, use the menu or launch
|
||||||
the two services one after the other as two separate calls to this
|
the two services one after the other as two separate calls to this
|
||||||
program.
|
program.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
VERSION_INFO = \
|
VERSION_INFO = \
|
||||||
"""
|
"""
|
||||||
Evennia {version}
|
Evennia {version}
|
||||||
{about}
|
{about}
|
||||||
OS: {os}
|
OS: {os}
|
||||||
Python: {python}
|
Python: {python}
|
||||||
Twisted: {twisted}
|
Twisted: {twisted}
|
||||||
Django: {django}
|
Django: {django}
|
||||||
{south}
|
"""
|
||||||
"""
|
|
||||||
|
|
||||||
ABOUT_INFO= \
|
ABOUT_INFO= \
|
||||||
"""
|
"""
|
||||||
MUD/MUX/MU* development system
|
Evennia MUD/MUX/MU* development system
|
||||||
|
|
||||||
Licence: BSD 3-Clause Licence
|
Licence: BSD 3-Clause Licence
|
||||||
Web: http://www.evennia.com
|
Web: http://www.evennia.com
|
||||||
Irc: #evennia on FreeNode
|
Irc: #evennia on FreeNode
|
||||||
Forum: http://www.evennia.com/discussions
|
Forum: http://www.evennia.com/discussions
|
||||||
Maintainer (2010-): Griatch (griatch AT gmail DOT com)
|
Maintainer (2010-): Griatch (griatch AT gmail DOT com)
|
||||||
Maintainer (2006-10): Greg Taylor
|
Maintainer (2006-10): Greg Taylor
|
||||||
"""
|
"""
|
||||||
|
|
||||||
HELP_ENTRY = \
|
HELP_ENTRY = \
|
||||||
"""
|
"""
|
||||||
(version %s)
|
See python evennia.py -h for controlling Evennia directly from
|
||||||
|
the command line.
|
||||||
All launcher functionality can be accessed directly from the command
|
|
||||||
line. See python evennia.py -h for options.
|
|
||||||
|
|
||||||
Evennia has two parts that both must run:
|
Evennia has two parts that both must run:
|
||||||
|
|
||||||
|
|
@ -212,89 +231,185 @@ MENU = \
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
#------------------------------------------------------------
|
||||||
#
|
#
|
||||||
# System Configuration and setup
|
# Functions
|
||||||
#
|
#
|
||||||
|
#------------------------------------------------------------
|
||||||
|
|
||||||
SERVER_PIDFILE = "server.pid"
|
def evennia_version():
|
||||||
PORTAL_PIDFILE = "portal.pid"
|
"""
|
||||||
|
Get the Evennia version info from the main package.
|
||||||
SERVER_RESTART = "server.restart"
|
"""
|
||||||
PORTAL_RESTART = "portal.restart"
|
version = "Unknown"
|
||||||
|
with open(os.path.join(EVENNIA_ROOT, "VERSION.txt"), 'r') as f:
|
||||||
# Get the settings
|
version = f.read().strip()
|
||||||
from django.conf import settings
|
|
||||||
|
|
||||||
from src.utils.utils import get_evennia_version
|
|
||||||
EVENNIA_VERSION = get_evennia_version()
|
|
||||||
|
|
||||||
# Setup access of the evennia server itself
|
|
||||||
SERVER_PY_FILE = os.path.join(settings.SRC_DIR, 'server/server.py')
|
|
||||||
PORTAL_PY_FILE = os.path.join(settings.SRC_DIR, 'server/portal.py')
|
|
||||||
|
|
||||||
# Get logfile names
|
|
||||||
SERVER_LOGFILE = settings.SERVER_LOG_FILE
|
|
||||||
PORTAL_LOGFILE = settings.PORTAL_LOG_FILE
|
|
||||||
|
|
||||||
# Add this to the environmental variable for the 'twistd' command.
|
|
||||||
currpath = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
||||||
if 'PYTHONPATH' in os.environ:
|
|
||||||
os.environ['PYTHONPATH'] += (":%s" % currpath)
|
|
||||||
else:
|
|
||||||
os.environ['PYTHONPATH'] = currpath
|
|
||||||
|
|
||||||
TWISTED_BINARY = 'twistd'
|
|
||||||
if os.name == 'nt':
|
|
||||||
# Windows needs more work to get the correct binary
|
|
||||||
try:
|
try:
|
||||||
# Test for for win32api
|
version = "%s(GIT %s)" % (version, os.popen("git rev-parse --short HEAD").read().strip())
|
||||||
import win32api
|
except IOError:
|
||||||
except ImportError:
|
pass
|
||||||
print """
|
return version
|
||||||
ERROR: Unable to import win32api, which Twisted requires to run.
|
|
||||||
You may download it from:
|
|
||||||
|
|
||||||
http://sourceforge.net/projects/pywin32
|
|
||||||
or
|
def init_game_directory(path):
|
||||||
http://starship.python.net/crew/mhammond/win32/Downloads.html"""
|
"""
|
||||||
|
Try to analyze the given path to find settings.py - this defines
|
||||||
|
the game directory and also sets PYTHONPATH as well as the
|
||||||
|
django path.
|
||||||
|
"""
|
||||||
|
global GAMEDIR
|
||||||
|
if os.path.exists(os.path.join(path, SETTINGFILE)):
|
||||||
|
# path given to server/conf/
|
||||||
|
GAMEDIR = os.path.dirname(os.path.dirname(os.path.dirname(path)))
|
||||||
|
elif os.path.exists(SETTINGS_PATH):
|
||||||
|
# path given to somewhere else in gamedir
|
||||||
|
GAMEDIR = os.path.dirname(os.path.dirname(path))
|
||||||
|
else:
|
||||||
|
# Assume path given to root game dir
|
||||||
|
GAMEDIR = path
|
||||||
|
|
||||||
|
# set pythonpath to gamedir
|
||||||
|
sys.path.insert(0, GAMEDIR)
|
||||||
|
# set the settings location
|
||||||
|
os.environ['DJANGO_SETTINGS_MODULE'] = SETTINGS_DOTPATH
|
||||||
|
# required since django1.7.
|
||||||
|
django.setup()
|
||||||
|
|
||||||
|
# check all dependencies
|
||||||
|
from evennia.utils.utils import check_evennia_dependencies
|
||||||
|
if not check_evennia_
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# test existence of settings module
|
||||||
|
try:
|
||||||
|
settings = importlib.import_module(SETTINGS_DOTPATH)
|
||||||
|
except Exception:
|
||||||
|
import traceback
|
||||||
|
print "\n" + traceback.format_exc()
|
||||||
|
print ERROR_SETTINGS
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
if not os.path.exists('twistd.bat'):
|
# set up the Evennia executables and log file locations
|
||||||
# Test for executable twisted batch file. This calls the twistd.py
|
global SERVER_PY_FILE, PORTAL_PY_FILE
|
||||||
# executable that is usually not found on the path in Windows.
|
global SERVER_LOGFILE, PORTAL_LOGFILE
|
||||||
# It's not enough to locate scripts.twistd, what we want is the
|
global SERVER_PIDFILE, PORTAL_PIDFILE
|
||||||
# executable script C:\PythonXX/Scripts/twistd.py. Alas we cannot
|
global SERVER_RESTART, PORTAL_RESTART
|
||||||
# hardcode this location since we don't know if user has Python
|
global EVENNIA_VERSION
|
||||||
# in a non-standard location, so we try to figure it out.
|
|
||||||
from twisted.scripts import twistd
|
|
||||||
twistd_path = os.path.abspath(
|
|
||||||
os.path.join(os.path.dirname(twistd.__file__),
|
|
||||||
os.pardir, os.pardir, os.pardir, os.pardir,
|
|
||||||
'scripts', 'twistd.py'))
|
|
||||||
bat_file = open('twistd.bat', 'w')
|
|
||||||
bat_file.write("@\"%s\" \"%s\" %%*" % (sys.executable, twistd_path))
|
|
||||||
bat_file.close()
|
|
||||||
print """
|
|
||||||
INFO: Since you are running Windows, a file 'twistd.bat' was
|
|
||||||
created for you. This is a simple batch file that tries to call
|
|
||||||
the twisted executable. Evennia determined this to be:
|
|
||||||
|
|
||||||
%(twistd_path)s
|
SERVER_PY_FILE = os.path.join(settings.LIB_DIR, "server/server.py")
|
||||||
|
PORTAL_PY_FILE = os.path.join(settings.LIB_DIR, "portal/server.py")
|
||||||
|
|
||||||
If you run into errors at startup you might need to edit
|
SERVER_PIDFILE = os.path.join(GAMEDIR, SERVERDIR, "server.pid")
|
||||||
twistd.bat to point to the actual location of the Twisted
|
PORTAL_PIDFILE = os.path.join(GAMEDIR, SERVERDIR, "portal.pid")
|
||||||
executable (usually called twistd.py) on your machine.
|
|
||||||
|
|
||||||
This procedure is only done once. Run evennia.py again when you
|
SERVER_RESTART = os.path.join(GAMEDIR, SERVERDIR, "server.restart")
|
||||||
are ready to start the server.
|
PORTAL_RESTART = os.path.join(GAMEDIR, SERVERDIR, "portal.restart")
|
||||||
""" % {'twistd_path': twistd_path}
|
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
TWISTED_BINARY = 'twistd.bat'
|
SERVER_LOGFILE = settings.SERVER_LOG_FILE
|
||||||
|
PORTAL_LOGFILE = settings.PORTAL_LOG_FILE
|
||||||
|
|
||||||
|
# This also tests the library access
|
||||||
|
from evennia.utils.utils import get_evennia_version
|
||||||
|
EVENNIA_VERSION = get_evennia_version()
|
||||||
|
|
||||||
|
# set up twisted
|
||||||
|
if os.name == 'nt':
|
||||||
|
# We need to handle Windows twisted separately. We create a
|
||||||
|
# batchfile in game/server, linking to the actual binary
|
||||||
|
|
||||||
|
global TWISTED_BINARY
|
||||||
|
TWISTED_BINARY = "twistd.bat"
|
||||||
|
|
||||||
|
# add path so system can find the batfile
|
||||||
|
sys.path.insert(0, os.path.join(GAMEDIR, SERVERDIR))
|
||||||
|
|
||||||
|
try:
|
||||||
|
importlib.import_module("win32api")
|
||||||
|
except ImportError:
|
||||||
|
print ERROR_WINDOWS_WIN32API
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
|
if not os.path.exists(os.path.join(EVENNIA_BIN, TWISTED_BINARY)):
|
||||||
|
# Test for executable twisted batch file. This calls the
|
||||||
|
# twistd.py executable that is usually not found on the
|
||||||
|
# path in Windows. It's not enough to locate
|
||||||
|
# scripts.twistd, what we want is the executable script
|
||||||
|
# C:\PythonXX/Scripts/twistd.py. Alas we cannot hardcode
|
||||||
|
# this location since we don't know if user has Python in
|
||||||
|
# a non-standard location. So we try to figure it out.
|
||||||
|
twistd = importlib.import_module("twisted.scripts.twistd")
|
||||||
|
twistd_dir = os.path.dirname(twistd.__file__)
|
||||||
|
|
||||||
|
# note that we hope the twistd package won't change here, since we
|
||||||
|
# try to get to the executable by relative path.
|
||||||
|
twistd_path = os.path.abspath(os.path.join(twistd_dir,
|
||||||
|
os.pardir, os.pardir, os.pardir, os.pardir,
|
||||||
|
'scripts', 'twistd.py'))
|
||||||
|
|
||||||
|
with open('twistd.bat', 'w') as bat_file:
|
||||||
|
# build a custom bat file for windows
|
||||||
|
bat_file.write("@\"%s\" \"%s\" %%*" % (sys.executable, twistd_path))
|
||||||
|
|
||||||
|
print INFO_WINDOWS_BATFILE.format(twistd_path=twistd_path)
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Check/Create settings
|
||||||
|
#
|
||||||
|
|
||||||
|
def create_secret_key():
|
||||||
|
"""
|
||||||
|
Randomly create the secret key for the settings file
|
||||||
|
"""
|
||||||
|
import random
|
||||||
|
import string
|
||||||
|
secret_key = list((string.letters +
|
||||||
|
string.digits + string.punctuation).replace("\\", "").replace("'", '"'))
|
||||||
|
random.shuffle(secret_key)
|
||||||
|
secret_key = "".join(secret_key[:40])
|
||||||
|
return secret_key
|
||||||
|
|
||||||
|
|
||||||
|
def create_settings_file():
|
||||||
|
"""
|
||||||
|
Uses the template settings file to build a working
|
||||||
|
settings file.
|
||||||
|
"""
|
||||||
|
settings_path = os.path.join(GAMEDIR, "server", "conf", "settings.py")
|
||||||
|
with open(settings_path, 'r') as f:
|
||||||
|
settings_string = f.read()
|
||||||
|
|
||||||
|
# tweak the settings
|
||||||
|
setting_dict = {"servername":"Evennia",
|
||||||
|
"secret_key":create_secret_key}
|
||||||
|
|
||||||
|
# modify the settings
|
||||||
|
settings_string.format(**setting_dict)
|
||||||
|
|
||||||
|
with open(settings_path, 'w') as f:
|
||||||
|
f.write(settingsj_string)
|
||||||
|
|
||||||
|
|
||||||
# Functions
|
# Functions
|
||||||
|
|
||||||
|
def create_game_directory(dirname):
|
||||||
|
"""
|
||||||
|
Initialize a new game directory named dirname
|
||||||
|
at the current path. This means copying the
|
||||||
|
template directory from evennia's root.
|
||||||
|
"""
|
||||||
|
global GAMEDIR
|
||||||
|
GAMEDIR = os.abspath(os.path.join(CURRENT_DIR, dirname))
|
||||||
|
if os.path.exists(GAMEDIR):
|
||||||
|
print "Cannot create new Evennia game dir: '%s' already exists." % dirname
|
||||||
|
sys.exit()
|
||||||
|
# copy template directory
|
||||||
|
shutil.copytree(EVENNIA_TEMPLATE, GAMEDIR)
|
||||||
|
# pre-build settings file in the new GAMEDIR
|
||||||
|
create_settings_file()
|
||||||
|
|
||||||
|
|
||||||
def get_pid(pidfile):
|
def get_pid(pidfile):
|
||||||
"""
|
"""
|
||||||
Get the PID (Process ID) by trying to access
|
Get the PID (Process ID) by trying to access
|
||||||
|
|
@ -351,25 +466,19 @@ def show_version_info(about=False):
|
||||||
import os, sys
|
import os, sys
|
||||||
import twisted
|
import twisted
|
||||||
import django
|
import django
|
||||||
try:
|
|
||||||
import south
|
|
||||||
sversion = "South %s" % south.__version__
|
|
||||||
except ImportError:
|
|
||||||
sversion = "South <not installed>"
|
|
||||||
|
|
||||||
return VERSION_INFO.format(version=EVENNIA_VERSION,
|
return VERSION_INFO.format(version=EVENNIA_VERSION,
|
||||||
about=ABOUT_INFO if about else "",
|
about=ABOUT_INFO if about else "",
|
||||||
os=os.name, python=sys.version.split()[0],
|
os=os.name, python=sys.version.split()[0],
|
||||||
twisted=twisted.version.short(),
|
twisted=twisted.version.short(),
|
||||||
django=django.get_version(),
|
django=django.get_version())
|
||||||
south=sversion)
|
|
||||||
|
|
||||||
def run_menu():
|
def run_menu():
|
||||||
"""
|
"""
|
||||||
This launches an interactive menu.
|
This launches an interactive menu.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
cmdstr = [sys.executable, "runner.py"]
|
cmdstr = [sys.executable, EVENNIA_RUNNER]
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
# menu loop
|
# menu loop
|
||||||
|
|
@ -405,7 +514,10 @@ def run_menu():
|
||||||
cmdstr.extend(['--iportal'])
|
cmdstr.extend(['--iportal'])
|
||||||
elif inp == 4:
|
elif inp == 4:
|
||||||
cmdstr.extend(['--iserver', '--iportal'])
|
cmdstr.extend(['--iserver', '--iportal'])
|
||||||
return cmdstr
|
# start server
|
||||||
|
cmdstr.append("start")
|
||||||
|
Popen(cmdstr)
|
||||||
|
return
|
||||||
elif inp < 10:
|
elif inp < 10:
|
||||||
if inp == 5:
|
if inp == 5:
|
||||||
if os.name == 'nt':
|
if os.name == 'nt':
|
||||||
|
|
@ -427,20 +539,18 @@ def run_menu():
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
print "Not a valid option."
|
print "Not a valid option."
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def handle_args(options, mode, service):
|
def server_operation(mode, service, interactive):
|
||||||
"""
|
"""
|
||||||
Handle argument options given on the command line.
|
Handle argument options given on the command line.
|
||||||
|
|
||||||
options - parsed object for command line
|
|
||||||
mode - str; start/stop etc
|
mode - str; start/stop etc
|
||||||
service - str; server, portal or all
|
service - str; server, portal or all
|
||||||
|
interactive - bool; use interactive mode or daemon
|
||||||
"""
|
"""
|
||||||
|
|
||||||
inter = options.interactive
|
cmdstr = [sys.executable, EVENNIA_RUNNER]
|
||||||
cmdstr = [sys.executable, "runner.py"]
|
|
||||||
errmsg = "The %s does not seem to be running."
|
errmsg = "The %s does not seem to be running."
|
||||||
|
|
||||||
if mode == 'start':
|
if mode == 'start':
|
||||||
|
|
@ -450,21 +560,23 @@ def handle_args(options, mode, service):
|
||||||
|
|
||||||
# starting one or many services
|
# starting one or many services
|
||||||
if service == 'server':
|
if service == 'server':
|
||||||
if inter:
|
if interactive:
|
||||||
cmdstr.append('--iserver')
|
cmdstr.append('--iserver')
|
||||||
cmdstr.append('--noportal')
|
cmdstr.append('--noportal')
|
||||||
elif service == 'portal':
|
elif service == 'portal':
|
||||||
if inter:
|
if interactive:
|
||||||
cmdstr.append('--iportal')
|
cmdstr.append('--iportal')
|
||||||
cmdstr.append('--noserver')
|
cmdstr.append('--noserver')
|
||||||
management.call_command('collectstatic', verbosity=1, interactive=False)
|
management.call_command('collectstatic', verbosity=1, interactive=False)
|
||||||
else: # all
|
else: # all
|
||||||
# for convenience we don't start logging of
|
# for convenience we don't start logging of
|
||||||
# portal, only of server with this command.
|
# portal, only of server with this command.
|
||||||
if inter:
|
if interactive:
|
||||||
cmdstr.extend(['--iserver'])
|
cmdstr.extend(['--iserver'])
|
||||||
management.call_command('collectstatic', verbosity=1, interactive=False)
|
management.call_command('collectstatic', verbosity=1, interactive=False)
|
||||||
return cmdstr
|
# start the server
|
||||||
|
cmdstr.append("start")
|
||||||
|
Popen(cmdstr)
|
||||||
|
|
||||||
elif mode == 'reload':
|
elif mode == 'reload':
|
||||||
# restarting services
|
# restarting services
|
||||||
|
|
@ -493,7 +605,6 @@ def handle_args(options, mode, service):
|
||||||
else:
|
else:
|
||||||
kill(PORTAL_PIDFILE, SIG, "Portal stopped.", errmsg % 'Portal', PORTAL_RESTART, restart=False)
|
kill(PORTAL_PIDFILE, SIG, "Portal stopped.", errmsg % 'Portal', PORTAL_RESTART, restart=False)
|
||||||
kill(SERVER_PIDFILE, SIG, "Server stopped.", errmsg % 'Server', restart="shutdown")
|
kill(SERVER_PIDFILE, SIG, "Server stopped.", errmsg % 'Server', restart="shutdown")
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def error_check_python_modules():
|
def error_check_python_modules():
|
||||||
|
|
@ -504,20 +615,16 @@ def error_check_python_modules():
|
||||||
the python source files themselves). Best they fail already here
|
the python source files themselves). Best they fail already here
|
||||||
before we get any further.
|
before we get any further.
|
||||||
"""
|
"""
|
||||||
def imp(path, split=True):
|
from django.conf import settings
|
||||||
mod, fromlist = path, "None"
|
|
||||||
if split:
|
|
||||||
mod, fromlist = path.rsplit('.', 1)
|
|
||||||
__import__(mod, fromlist=[fromlist])
|
|
||||||
|
|
||||||
# core modules
|
# core modules
|
||||||
imp(settings.COMMAND_PARSER)
|
importlib.import_module(settings.COMMAND_PARSER)
|
||||||
imp(settings.SEARCH_AT_RESULT)
|
importlib.import_module(settings.SEARCH_AT_RESULT)
|
||||||
imp(settings.SEARCH_AT_MULTIMATCH_INPUT)
|
importlib.import_module(settings.SEARCH_AT_MULTIMATCH_INPUT)
|
||||||
imp(settings.CONNECTION_SCREEN_MODULE, split=False)
|
importlib.import_module(settings.CONNECTION_SCREEN_MODULE, split=False)
|
||||||
#imp(settings.AT_INITIAL_SETUP_HOOK_MODULE, split=False)
|
#imp(settings.AT_INITIAL_SETUP_HOOK_MODULE, split=False)
|
||||||
for path in settings.LOCK_FUNC_MODULES:
|
for path in settings.LOCK_FUNC_MODULES:
|
||||||
imp(path, split=False)
|
importlib.import_module(path, split=False)
|
||||||
# cmdsets
|
# cmdsets
|
||||||
|
|
||||||
deprstring = "settings.%s should be renamed to %s. If defaults are used, " \
|
deprstring = "settings.%s should be renamed to %s. If defaults are used, " \
|
||||||
|
|
@ -541,12 +648,13 @@ def error_check_python_modules():
|
||||||
if not cmdsethandler.import_cmdset(settings.CMDSET_CHARACTER, None): print "Warning: CMDSET_CHARACTER failed to load"
|
if not cmdsethandler.import_cmdset(settings.CMDSET_CHARACTER, None): print "Warning: CMDSET_CHARACTER failed to load"
|
||||||
if not cmdsethandler.import_cmdset(settings.CMDSET_PLAYER, None): print "Warning: CMDSET_PLAYER failed to load"
|
if not cmdsethandler.import_cmdset(settings.CMDSET_PLAYER, None): print "Warning: CMDSET_PLAYER failed to load"
|
||||||
# typeclasses
|
# typeclasses
|
||||||
imp(settings.BASE_PLAYER_TYPECLASS)
|
importlib.import_module(settings.BASE_PLAYER_TYPECLASS)
|
||||||
imp(settings.BASE_OBJECT_TYPECLASS)
|
importlib.import_module(settings.BASE_OBJECT_TYPECLASS)
|
||||||
imp(settings.BASE_CHARACTER_TYPECLASS)
|
importlib.import_module(settings.BASE_CHARACTER_TYPECLASS)
|
||||||
imp(settings.BASE_ROOM_TYPECLASS)
|
importlib.import_module(settings.BASE_ROOM_TYPECLASS)
|
||||||
imp(settings.BASE_EXIT_TYPECLASS)
|
importlib.import_module(settings.BASE_EXIT_TYPECLASS)
|
||||||
imp(settings.BASE_SCRIPT_TYPECLASS)
|
importlib.import_module(settings.BASE_SCRIPT_TYPECLASS)
|
||||||
|
|
||||||
|
|
||||||
def create_database():
|
def create_database():
|
||||||
from django.core.management import call_command
|
from django.core.management import call_command
|
||||||
|
|
@ -554,32 +662,25 @@ def create_database():
|
||||||
call_command("migrate", interactive=False)
|
call_command("migrate", interactive=False)
|
||||||
print "\n ... database initialized.\n"
|
print "\n ... database initialized.\n"
|
||||||
|
|
||||||
|
|
||||||
def create_superuser():
|
def create_superuser():
|
||||||
from django.core.management import call_command
|
from django.core.management import call_command
|
||||||
print "\nCreate a superuser below. The superuser is Player #1, the 'owner' account of the server.\n"
|
print "\nCreate a superuser below. The superuser is Player #1, the 'owner' account of the server.\n"
|
||||||
call_command("createsuperuser", interactive=True)
|
call_command("createsuperuser", interactive=True)
|
||||||
|
|
||||||
|
|
||||||
def check_database(automigrate=False):
|
def check_database(automigrate=False):
|
||||||
# Check so a database exists and is accessible
|
# Check so a database exists and is accessible
|
||||||
from django.db import DatabaseError
|
from django.db import DatabaseError
|
||||||
from src.players.models import PlayerDB
|
from src.players.models import PlayerDB
|
||||||
try:
|
try:
|
||||||
superuser = PlayerDB.objects.get(id=1)
|
PlayerDB.objects.get(id=1)
|
||||||
except DatabaseError, e:
|
except DatabaseError, e:
|
||||||
if automigrate:
|
if automigrate:
|
||||||
create_database()
|
create_database()
|
||||||
create_superuser()
|
create_superuser()
|
||||||
else:
|
else:
|
||||||
print """
|
print ERROR_DATABASE.format(traceback=e)
|
||||||
Your database does not seem to be set up correctly.
|
|
||||||
(error was '%s')
|
|
||||||
|
|
||||||
Try to run
|
|
||||||
|
|
||||||
python evennia.py
|
|
||||||
|
|
||||||
to initialize the database according to your settings.
|
|
||||||
""" % e
|
|
||||||
sys.exit()
|
sys.exit()
|
||||||
except PlayerDB.DoesNotExist:
|
except PlayerDB.DoesNotExist:
|
||||||
# no superuser yet. We need to create it.
|
# no superuser yet. We need to create it.
|
||||||
|
|
@ -587,71 +688,60 @@ def check_database(automigrate=False):
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""
|
"""
|
||||||
This handles command line input.
|
Run the evennia main program.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
parser = OptionParser(usage="%prog [-i] start|stop|reload|menu [server|portal]|manager args",
|
# set up argument parser
|
||||||
|
|
||||||
|
parser = ArgumentParser(#usage="%prog [-i] start|stop|reload|menu [server|portal]|manager args",
|
||||||
description=CMDLINE_HELP)
|
description=CMDLINE_HELP)
|
||||||
parser.add_option('-i', '--interactive', action='store_true',
|
parser.add_argument('-i', '--interactive', action='store_true',
|
||||||
dest='interactive', default=False,
|
dest='interactive', default=False,
|
||||||
help="Start given processes in interactive mode.")
|
help="Start given processes in interactive mode.")
|
||||||
parser.add_option('-v', '--version', action='store_true',
|
parser.add_argument('-v', '--version', action='store_true',
|
||||||
dest='show_version', default=False,
|
dest='show_version', default=False,
|
||||||
help="Show version info.")
|
help="Show version info.")
|
||||||
|
parser.add_argument('--init', action='store', dest="init", metavar="dirname")
|
||||||
|
parser.add_argument('-c', '--config', action='store', dest="config", default=None)
|
||||||
|
parser.add_argument("mode", default="menu")
|
||||||
|
parser.add_argument("service", choices=["all", "server", "portal"], default="all")
|
||||||
|
|
||||||
options, args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
if not args:
|
# handle arguments
|
||||||
if options.show_version:
|
|
||||||
print show_version_info()
|
|
||||||
return
|
|
||||||
mode = "menu"
|
|
||||||
service = 'all'
|
|
||||||
if args:
|
|
||||||
mode = args[0]
|
|
||||||
service = "all"
|
|
||||||
if len(args) > 1:
|
|
||||||
service = args[1]
|
|
||||||
|
|
||||||
if mode in ["start", "menu"]:
|
if args.show_version:
|
||||||
check_database(True)
|
print show_version_info()
|
||||||
elif mode not in ["stop"]:
|
|
||||||
check_database(False)
|
|
||||||
|
|
||||||
if mode not in ['menu', 'start', 'reload', 'stop']:
|
mode, service = args.mode, args.service
|
||||||
from django.core.management import call_command
|
|
||||||
call_command(mode)
|
if args.init:
|
||||||
sys.exit()
|
create_game_directory(args.init)
|
||||||
if service not in ['server', 'portal', 'all']:
|
|
||||||
print "service should be none, 'server', 'portal' or 'all'."
|
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
|
# this must be done first - it sets up all the global properties
|
||||||
|
# and initializes django for the game directory
|
||||||
|
init_game_directory(CURRENT_DIR)
|
||||||
|
|
||||||
if mode == 'menu':
|
if mode == 'menu':
|
||||||
# launch menu
|
# launch menu for operation
|
||||||
cmdstr = run_menu()
|
check_database(True)
|
||||||
|
run_menu()
|
||||||
|
elif mode in ('start', 'reload', 'stop'):
|
||||||
|
# operate the server directly
|
||||||
|
if mode != "stop":
|
||||||
|
check_database(False)
|
||||||
|
server_operation(mode, service, args.interactive)
|
||||||
else:
|
else:
|
||||||
# handle command-line arguments
|
# pass-through to django manager
|
||||||
cmdstr = handle_args(options, mode, service)
|
from django.core.management import call_command
|
||||||
if cmdstr:
|
call_command(mode)
|
||||||
# call the runner.
|
|
||||||
cmdstr.append('start')
|
|
||||||
Popen(cmdstr)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
# start Evennia
|
# start Evennia from the command line
|
||||||
|
|
||||||
if _CREATED_SETTINGS:
|
|
||||||
# if settings were created, info has already been printed.
|
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
from src.utils.utils import check_evennia_dependencies
|
|
||||||
if check_evennia_dependencies():
|
if check_evennia_dependencies():
|
||||||
if len(sys.argv) > 1 and sys.argv[1] in ('runserver', 'testserver'):
|
if len(sys.argv) > 1 and sys.argv[1] in ('runserver', 'testserver'):
|
||||||
print """
|
print WARNING_RUNSERVER
|
||||||
WARNING: There is no need to run the Django development
|
|
||||||
webserver to test out Evennia web features (the web client
|
|
||||||
will in fact not work since the Django test server knows
|
|
||||||
nothing about MUDs). Instead, just start Evennia with the
|
|
||||||
webserver component active (this is the default).
|
|
||||||
"""
|
|
||||||
main()
|
main()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue