evennia/src/server/initial_setup.py

271 lines
10 KiB
Python
Raw Normal View History

"""
This module handles initial database propagation, which is only run the first
time the game starts. It will create some default channels, objects, and
other things.
Everything starts at handle_setup()
"""
from django.contrib.auth.models import User
from django.core import management
from django.conf import settings
from src.server.models import ServerConfig
from src.help.models import HelpEntry
2012-03-30 23:57:04 +02:00
from src.utils import create
# i18n
from django.utils.translation import ugettext as _
def create_config_values():
"""
Creates the initial config values.
2012-03-30 23:57:04 +02:00
"""
ServerConfig.objects.conf("site_name", settings.SERVERNAME)
ServerConfig.objects.conf("idle_timeout", settings.IDLE_TIMEOUT)
def get_god_user():
"""
Returns the initially created 'god' User object.
"""
return User.objects.get(id=1)
def create_objects():
"""
Creates the #1 player and Limbo room.
"""
2012-03-30 23:57:04 +02:00
print _(" Creating objects (Player #1 and Limbo room) ...")
# Set the initial User's account object's username on the #1 object.
2012-03-30 23:57:04 +02:00
# This object is pure django and only holds name, email and password.
god_user = get_god_user()
# Create a Player 'user profile' object to hold eventual
# mud-specific settings for the bog standard User object. This is
# accessed by user.get_profile() and can also store attributes.
# It also holds mud permissions, but for a superuser these
2012-03-30 23:57:04 +02:00
# have no effect anyhow.
character_typeclass = settings.BASE_CHARACTER_TYPECLASS
# Create the Player object as well as the in-game god-character
# for user #1. We can't set location and home yet since nothing
# exists. Also, all properties (name, email, password, is_superuser)
2012-03-30 23:57:04 +02:00
# is inherited from the user so we don't specify it again here.
2012-03-30 23:57:04 +02:00
god_character = create.create_player(god_user.username, None, None,
user=god_user,
create_character=True,
character_typeclass=character_typeclass)
god_character.id = 1
god_character.db.desc = _('This is User #1.')
god_character.locks.add("examine:perm(Immortals);edit:false();delete:false();boot:false();msg:all();puppet:false()")
god_character.save()
2012-03-30 23:57:04 +02:00
# Limbo is the default "nowhere" starting room
room_typeclass = settings.BASE_ROOM_TYPECLASS
limbo_obj = create.create_object(room_typeclass, _('Limbo'))
limbo_obj.id = 2
string = " ".join([
"Welcome to your new {wEvennia{n-based game. From here you are ready to begin development.",
"Visit http://evennia.com if you should need help or would like to participate in community discussions.",
"If you are logged in as User #1 you can create a demo/tutorial area with '@batchcommand contrib.tutorial_world.build'.",
"Log out and create a new non-admin account at the login screen to play the tutorial properly."])
string = _(string)
limbo_obj.db.desc = string
limbo_obj.save()
# Now that Limbo exists, try to set the user up in Limbo (unless
# the creation hooks already fixed this).
2012-03-30 23:57:04 +02:00
if not god_character.location:
god_character.location = limbo_obj
if not god_character.home:
god_character.home = limbo_obj
2012-03-30 23:57:04 +02:00
def create_channels():
"""
Creates some sensible default channels.
"""
print _(" Creating default channels ...")
# public channel
key, aliases, desc, locks = settings.CHANNEL_PUBLIC
pchan = create.create_channel(key, aliases, desc, locks=locks)
2012-03-30 23:57:04 +02:00
# mudinfo channel
key, aliases, desc, locks = settings.CHANNEL_MUDINFO
ichan = create.create_channel(key, aliases, desc, locks=locks)
# connectinfo channel
key, aliases, desc, locks = settings.CHANNEL_CONNECTINFO
cchan = create.create_channel(key, aliases, desc, locks=locks)
# connect the god user to all these channels by default.
goduser = get_god_user()
from src.comms.models import PlayerChannelConnection
PlayerChannelConnection.objects.create_connection(goduser, pchan)
PlayerChannelConnection.objects.create_connection(goduser, ichan)
PlayerChannelConnection.objects.create_connection(goduser, cchan)
2012-03-30 23:57:04 +02:00
def import_MUX_help_files():
"""
Imports the MUX help files.
2012-03-30 23:57:04 +02:00
"""
print _(" Importing MUX help database (devel reference only) ...")
2012-03-30 23:57:04 +02:00
management.call_command('loaddata', '../src/help/mux_help_db.json', verbosity=0)
# categorize the MUX help files into its own category.
default_category = "MUX"
print _(" Moving imported help db to help category '%(default)s'." \
% {'default': default_category})
HelpEntry.objects.all_to_category(default_category)
2012-03-30 23:57:04 +02:00
def create_system_scripts():
"""
Setup the system repeat scripts. They are automatically started
2012-03-30 23:57:04 +02:00
by the create_script function.
"""
from src.scripts import scripts
print _(" Creating and starting global scripts ...")
2012-03-30 23:57:04 +02:00
# check so that all sessions are alive.
script1 = create.create_script(scripts.CheckSessions)
# validate all scripts in script table.
script2 = create.create_script(scripts.ValidateScripts)
# update the channel handler to make sure it's in sync
script3 = create.create_script(scripts.ValidateChannelHandler)
# clear the attribute cache regularly
script4 = create.create_script(scripts.ClearAttributeCache)
if not script1 or not script2 or not script3 or not script4:
print _(" Error creating system scripts.")
2012-03-30 23:57:04 +02:00
def start_game_time():
"""
This starts a persistent script that keeps track of the
in-game time (in whatever accelerated reference frame), but also
the total run time of the server as well as its current uptime
(the uptime can also be found directly from the server though).
"""
print _(" Starting in-game time ...")
from src.utils import gametime
gametime.init_gametime()
def create_admin_media_links():
"""
This traverses to src/web/media and tries to create a symbolic
2012-03-30 23:57:04 +02:00
link to the django media files from within the MEDIA_ROOT.
These are files we normally don't
want to mess with (use templates to customize the admin
look). Linking is needed since the Twisted webserver otherwise has no
notion of where the default files are - and we cannot hard-code it
since the django install may be at different locations depending
on system.
"""
import django, os
if django.get_version() < 1.4:
dpath = os.path.join(django.__path__[0], 'contrib', 'admin', 'media')
else:
dpath = os.path.join(django.__path__[0], 'contrib', 'admin', 'static', 'admin')
apath = os.path.join(settings.ADMIN_MEDIA_ROOT)
if os.path.isdir(apath):
print _(" ADMIN_MEDIA_ROOT already exists. Ignored.")
2012-03-30 23:57:04 +02:00
return
if os.name == 'nt':
print _(" Admin-media files copied to ADMIN_MEDIA_ROOT (Windows mode).")
os.mkdir(apath)
os.system('xcopy "%s" "%s" /e /q /c' % (dpath, apath))
if os.name == 'posix':
try:
os.symlink(dpath, apath)
print _(" Admin-media symlinked to ADMIN_MEDIA_ROOT.")
except OSError, e:
print _(" There was an error symlinking Admin-media to ADMIN_MEDIA_ROOT:\n %s\n -> \n %s\n (%s)\n If you see issues, link manually." % (dpath, apath, e))
else:
print _(" Admin-media files should be copied manually to ADMIN_MEDIA_ROOT.")
def at_initial_setup():
"""
Custom hook for users to overload some or all parts of the initial
setup. Called very last in the sequence. It tries to import and
run a module settings.AT_INITIAL_SETUP_HOOK_MODULE and will fail
silently if this does not exist or fails to load.
"""
modname = settings.AT_INITIAL_SETUP_HOOK_MODULE
if not modname:
2012-03-30 23:57:04 +02:00
return
try:
mod = __import__(modname, fromlist=[None])
except (ImportError, ValueError):
2012-03-30 23:57:04 +02:00
return
print _(" Running at_initial_setup() hook.")
if mod.__dict__.get("at_initial_setup", None):
2012-03-30 23:57:04 +02:00
mod.at_initial_setup()
def handle_setup(last_step):
"""
Main logic for the module. It allows for restarting
2012-03-30 23:57:04 +02:00
the initialization at any point if one of the modules
should crash.
"""
if last_step < 0:
# this means we don't need to handle setup since
2012-03-30 23:57:04 +02:00
# it already ran sucessfully once.
return
elif last_step == None:
# config doesn't exist yet. First start of server
last_step = 0
2012-03-30 23:57:04 +02:00
# setting up the list of functions to run
setup_queue = [
2012-03-30 23:57:04 +02:00
create_config_values,
create_objects,
create_channels,
create_system_scripts,
start_game_time,
create_admin_media_links,
import_MUX_help_files,
at_initial_setup]
if not settings.IMPORT_MUX_HELP:
2012-03-30 23:57:04 +02:00
# skip importing of the MUX helpfiles, they are
# not interesting except for developers.
del setup_queue[-2]
2012-03-30 23:57:04 +02:00
#print " Initial setup: %s steps." % (len(setup_queue))
# step through queue, from last completed function
2012-03-30 23:57:04 +02:00
for num, setup_func in enumerate(setup_queue[last_step:]):
# run the setup function. Note that if there is a
# traceback we let it stop the system so the config
2012-03-30 23:57:04 +02:00
# step is not saved.
#print "%s..." % num
try:
setup_func()
except Exception:
if last_step + num == 2:
from src.players.models import PlayerDB
from src.objects.models import ObjectDB
for obj in ObjectDB.objects.all():
obj.delete()
for profile in PlayerDB.objects.all():
profile.delete()
elif last_step + num == 3:
from src.comms.models import Channel, PlayerChannelConnection
for chan in Channel.objects.all():
chan.delete()
for conn in PlayerChannelConnection.objects.all():
conn.delete()
2012-03-30 23:57:04 +02:00
raise
ServerConfig.objects.conf("last_initial_setup_step", last_step + num + 1)
# We got through the entire list. Set last_step to -1 so we don't
# have to run this again.
2012-03-30 23:57:04 +02:00
ServerConfig.objects.conf("last_initial_setup_step", -1)