#MUDPyE - (M)ulti-(U)ser (D)imension (Py)thon (E)ngine
#Copyright (C) 2005  Corey Staten

#This program is free software; you can redistribute it and/or
#modify it under the terms of the GNU General Public License
#as published by the Free Software Foundation; either version 2
#of the License, or (at your option) any later version.

#This program is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#GNU General Public License for more details.

#You should have received a copy of the GNU General Public License
#along with this program; if not, write to the Free Software
#Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

#Send feedback/questions to MUDPyE@gmail.com

import sys
import time
import mptraceback

import mpdatabase
import mpcallback
import mploader
import mplog
import mpserver

from mpmudobject import Ex

#World Properties File Keys:
#  SourceBackupPath - Backup path for the source database.
#  ObjectBackupPath - Backup path for the object database.
#  SourceDatabaseFile - Name of the source database file.
#  ScriptGlobalsFile - Name of file to load script globals from.
#  ObjectDatabaseFile - Name of the object database file.
#  ObjectCacheSize - Size of the object datbase cache(in objects).
#  TransitionsFile - Name of the Transitions file.
#  ObjectIndexFile - Name of the Object Index File.
#  StartupArgsFile - Name of the startup arguments file.
#  WorldObjectID - ID of the world object.
#  WorldObjectType - Type of the world object.

class MudWorld(object):
  def __init__(self):
    pass

  def Boot(self, worldFile, logConfigFile):
    self.mudTraceback = []
    self.worldFile = worldFile
    self.logConfigFile = logConfigFile
    self.loggers = mplog.InitLogging(mudWorld, logConfigFile)
    self.worldProperties = mploader.ReadPropertiesFile(mudWorld, worldFile)
    self.worldObjID = self.worldProperties["WorldObjectID"]
    self.worldObjType = self.worldProperties["WorldObjectType"]
    #Logging object defaults to world object, can be set differently by the mud at runtime if wanted.
    #Logging object is NOT CREATED, it is only used if it already exists.
    self.loggingObjID = self.worldObjID
    self.sourceBackupPath = self.worldProperties["SourceBackupPath"]
    self.objectBackupPath = self.worldProperties["ObjectBackupPath"]
    self.bootTime = time.time()
    self.dns = mpserver.DNSThread()
    self.servers = []
    self.shutdown = False
    self.transitions = mploader.ReadTransitionFile(self, self.worldProperties["TransitionsFile"])
    self.objIndex = mploader.ReadIndexFile(self, self.worldProperties["ObjectIndexFile"])
    self.callbackHandler = mpcallback.CallbackHandler(mudWorld)
    self.objDB = mpdatabase.ObjectDatabase(self, self.worldProperties["ObjectDatabaseFile"])
    self.sourceDB = mpdatabase.SourceDatabase(self, self.worldProperties["SourceDatabaseFile"],
                                              self.worldProperties["ScriptGlobalsFile"])
    bootArgs = mploader.ReadPropertiesFile(self, self.worldProperties["StartupArgsFile"])
    #Attempt to load the world object.  If you can't, create it.
    if not self.objDB.HasObj(self.worldObjID):
      self.objDB.CreateObjAsID(self.worldObjID, self.worldObjType)
    Ex(self.objDB.GetObjRef(self.worldObjID), "_Sys_Boot", bootArgs=bootArgs)

  def Unboot(self):
    Ex(self.objDB.GetObjRef(self.worldObjID), "_Sys_Unboot")
    for server in self.servers:
      server.Shutdown()
    self.objDB.EmptyCache()
    self.objDB.CloseDB()
    self.sourceDB.CloseDB()

  def MudLoop(self):
    lastCycle = time.clock()
    lastDBCycle = time.clock()
    eventTime = 0
    while not(self.shutdown):
      #Run mud events.
      newCycle = time.clock()
      self.callbackHandler.ProcessTime(newCycle - lastCycle)
      #Save the database every 10 seconds.
      if (newCycle - lastDBCycle) > 10:
        self.objDB._SaveDirtyObjs()
        lastDBCycle = newCycle
      #Update network.
      for server in self.servers:
        server.AcceptConnections()
        server.NetworkUpdate()
      lastCycle = newCycle
      time.sleep(.1)

mudWorld = MudWorld()

if __name__ == "__main__":
  if len(sys.argv) < 3:
    print "Usage: python mpmain.py worldfile logconfig"
  else:
    try:
      mudWorld.Boot(sys.argv[1], sys.argv[2])
      mudWorld.MudLoop()
      mudWorld.Unboot()
    except:
      dumpFile = file("traceback.txt", "w")
      dumpFile.write(mptraceback.format_exc())
      dumpFile.close()
      raise