evennia/src/server/server.py

156 lines
5.6 KiB
Python
Raw Normal View History

"""
This module implements the main Evennia
server process, the core of the game engine.
"""
import time
import sys
import os
if os.name == 'nt':
# For Windows batchfile we need an extra path insertion here.
sys.path.insert(0, os.path.dirname(os.path.dirname(
os.path.dirname(os.path.abspath(__file__)))))
from twisted.application import internet, service
from twisted.internet import protocol, reactor
from django.db import connection
from django.conf import settings
from src.config.models import ConfigValue
from src.server.session import SessionProtocol
from src.server import sessionhandler
from src.server import initial_setup
from src.utils import reloads
from src.utils.utils import get_evennia_version
from src.comms import channelhandler
class EvenniaService(service.Service):
"""
The main server service task.
"""
def __init__(self):
# Holds the TCP services.
self.service_collection = None
self.game_running = True
sys.path.append('.')
# Database-specific startup optimizations.
if (settings.DATABASE_ENGINE == "sqlite3"
or hasattr(settings, 'DATABASE')
and settings.DATABASE.get('ENGINE', None) == 'django.db.backends.sqlite3'):
# run sqlite3 preps
self.sqlite3_prep()
# Begin startup debug output.
print '\n' + '-'*50
last_initial_setup_step = \
ConfigValue.objects.conf('last_initial_setup_step')
if not last_initial_setup_step:
# None is only returned if the config does not exist,
# i.e. this is an empty DB that needs populating.
print ' Server started for the first time. Setting defaults.'
initial_setup.handle_setup(0)
print '-'*50
elif int(last_initial_setup_step) >= 0:
# last_setup_step >= 0 means the setup crashed
# on one of its modules and setup will resume, retrying
# the last failed module. When all are finished, the step
# is set to -1 to show it does not need to be run again.
print ' Resuming initial setup from step %s.' % \
last_initial_setup_step
initial_setup.handle_setup(int(last_initial_setup_step))
print '-'*50
# we have to null this here.
sessionhandler.change_session_count(0)
self.start_time = time.time()
# initialize channelhandler
channelhandler.CHANNELHANDLER.update()
# init all global scripts
reloads.reload_scripts(init_mode=True)
# Make output to the terminal.
print ' %s (%s) started on port(s):' % \
(settings.SERVERNAME, get_evennia_version())
for port in settings.GAMEPORTS:
print ' * %s' % (port)
print '-'*50
# Server startup methods
def sqlite3_prep(self):
"""
Optimize some SQLite stuff at startup since we
can't save it to the database.
"""
cursor = connection.cursor()
cursor.execute("PRAGMA cache_size=10000")
cursor.execute("PRAGMA synchronous=OFF")
cursor.execute("PRAGMA count_changes=OFF")
cursor.execute("PRAGMA temp_store=2")
# General methods
def shutdown(self, message=None):
"""
Gracefully disconnect everyone and kill the reactor.
"""
if not message:
message = 'The server has been shutdown. Please check back soon.'
sessionhandler.announce_all(message)
sessionhandler.disconnect_all_sessions()
reactor.callLater(0, reactor.stop)
def getEvenniaServiceFactory(self):
"Retrieve instances of the server"
factory = protocol.ServerFactory()
factory.protocol = SessionProtocol
factory.server = self
return factory
def start_services(self, application):
"""
Starts all of the TCP services.
"""
self.service_collection = service.IServiceCollection(application)
for port in settings.GAMEPORTS:
evennia_server = \
internet.TCPServer(port, self.getEvenniaServiceFactory())
evennia_server.setName('Evennia%s' %port)
evennia_server.setServiceParent(self.service_collection)
if settings.IMC2_ENABLED:
from src.imc2.connection import IMC2ClientFactory
from src.imc2 import events as imc2_events
imc2_factory = IMC2ClientFactory()
svc = internet.TCPClient(settings.IMC2_SERVER_ADDRESS,
settings.IMC2_SERVER_PORT,
imc2_factory)
svc.setName('IMC2')
svc.setServiceParent(self.service_collection)
imc2_events.add_events()
if settings.IRC_ENABLED:
from src.irc.connection import IRC_BotFactory
irc = internet.TCPClient(settings.IRC_NETWORK,
settings.IRC_PORT,
IRC_BotFactory(settings.IRC_CHANNEL,
settings.IRC_NETWORK,
settings.IRC_NICKNAME))
irc.setName("%s:%s" % ("IRC", settings.IRC_CHANNEL))
irc.setServiceParent(self.service_collection)
# Twisted requires us to define an 'application' attribute.
application = service.Application('Evennia')
# The main mud service. Import this for access to the server methods.
mud_service = EvenniaService()
mud_service.start_services(application)