mirror of
https://github.com/evennia/evennia.git
synced 2026-03-22 15:56:30 +01:00
156 lines
5.6 KiB
Python
156 lines
5.6 KiB
Python
|
|
"""
|
||
|
|
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)
|