import sys import os import time import builtins from panda3d.core import * from direct.showbase import DConfig from direct.showbase.MessengerGlobal import * from direct.showbase.DirectObject import DirectObject from direct.showbase.EventManagerGlobal import * from direct.task.MiniTask import MiniTaskManager from direct.directnotify.DirectNotifyGlobal import * class LogAndOutput: def __init__(self, orig, log): self.orig = orig self.log = log self.console = False def write(self, str): self.log.write(str) self.log.flush() if self.console: self.orig.write(str) self.orig.flush() def flush(self): self.log.flush() self.orig.flush() class LauncherBase(DirectObject): GameName = 'game' GameLogFilenameKey = 'GAMELOG_FILENAME' PandaWindowOpenKey = 'PANDA_WINDOW_OPEN' PandaErrorCodeKey = 'PANDA_ERROR_CODE' NewInstallationKey = 'IS_NEW_INSTALLATION' LastLoginKey = 'LAST_LOGIN' UserLoggedInKey = 'USER_LOGGED_IN' PaidUserLoggedInKey = 'PAID_USER_LOGGED_IN' ReferrerKey = 'REFERRER_CODE' PeriodTimeRemainingKey = 'PERIOD_TIME_REMAINING' PeriodNameKey = 'PERIOD_NAME' SwidKey = 'SWID' DISLTokenKey = 'DISLTOKEN' def __init__(self): self.started = False self.taskMgrStarted = False self.pandaErrorCode = 0 ltime = time.localtime() logSuffix = '%02d%02d%02d_%02d%02d%02d' % (ltime[0] - 2000, ltime[1], ltime[2], ltime[3], ltime[4], ltime[5]) logPrefix = self.getLogFileName() + '-' logfile = logPrefix + logSuffix + '.log' self.errorfile = 'errorCode' log = open(logfile, 'a') logOut = LogAndOutput(sys.__stdout__, log) logErr = LogAndOutput(sys.__stderr__, log) sys.stdout = logOut sys.stderr = logErr print('\n\nStarting %s...' % self.GameName) print('Current time: ' + time.asctime(time.localtime(time.time())) + ' ' + time.tzname[0]) print('sys.path = ', sys.path) print('sys.argv = ', sys.argv) launcherConfig = DConfig builtins.config = launcherConfig if config.GetBool('log-private-info', 0): print('os.environ = ', os.environ) self.miniTaskMgr = MiniTaskManager() self.setServerVersion(launcherConfig.GetString('server-version', 'no_version_set')) self.nout = MultiplexStream() Notify.ptr().setOstreamPtr(self.nout, 0) self.nout.addFile(Filename(logfile)) if launcherConfig.GetBool('console-output', 0): self.nout.addStandardOutput() sys.stdout.console = True sys.stderr.console = True self.notify = directNotify.newCategory('Launcher') self.clock = TrueClock.getGlobalPtr() self.logPrefix = logPrefix self.testServerFlag = self.getTestServerFlag() self.notify.info('isTestServer: %s' % self.testServerFlag) self.gameServer = self.getGameServer() self.notify.info('Game Server %s' % self.gameServer) self.goUserName = '' self.lastLauncherMsg = None self.setRegistry(self.GameLogFilenameKey, logfile) self.showPhase = 3.5 self.currentPhase = 4 if self.getServerVersion() == 'no_version_set': self.setPandaErrorCode(10) self.notify.info('Aborting, Configrc did not run!') sys.exit() self.launcherMessage(self.Localizer.LauncherStartingMessage) self.http = HTTPClient() self.foreground() return def getTime(self): return self.clock.getShortTime() def isDummy(self): return 0 def background(self): self.notify.info('background: Launcher now operating in background') self.backgrounded = 1 def foreground(self): self.notify.info('foreground: Launcher now operating in foreground') self.backgrounded = 0 def setRegistry(self, key, value): self.notify.info('DEPRECATED setRegistry: %s = %s' % (key, value)) def getRegistry(self, key): self.notify.info('DEPRECATED getRegistry: %s' % key) return None def maybeStartGame(self): if not self.started and self.currentPhase >= self.showPhase: self.started = True self.notify.info('maybeStartGame: starting game') self.launcherMessage(self.Localizer.LauncherStartingGame) self.background() builtins.launcher = self self.startGame() def _runTaskManager(self): if not self.taskMgrStarted: self.miniTaskMgr.run() self.notify.info('Switching task managers.') taskMgr.run() def _stepMiniTaskManager(self, task): self.miniTaskMgr.step() if self.miniTaskMgr.taskList: return task.cont self.notify.info('Stopping mini task manager.') self.miniTaskMgr = None return task.done def _addMiniTask(self, task, name): if not self.miniTaskMgr: self.notify.info('Restarting mini task manager.') self.miniTaskMgr = MiniTaskManager() from direct.task.TaskManagerGlobal import taskMgr taskMgr.remove('miniTaskManager') taskMgr.add(self._stepMiniTaskManager, 'miniTaskManager') self.miniTaskMgr.add(task, name) def newTaskManager(self): self.taskMgrStarted = True if self.miniTaskMgr.running: self.miniTaskMgr.stop() from direct.task.TaskManagerGlobal import taskMgr taskMgr.remove('miniTaskManager') taskMgr.add(self._stepMiniTaskManager, 'miniTaskManager') def mainLoop(self): try: self._runTaskManager() except SystemExit: if hasattr(builtins, 'base'): base.destroy() self.notify.info('Normal exit.') raise except: self.setPandaErrorCode(12) self.notify.warning('Handling Python exception.') if hasattr(builtins, 'base') and getattr(base, 'cr', None): if base.cr.timeManager: from otp.otpbase import OTPGlobals base.cr.timeManager.setDisconnectReason(OTPGlobals.DisconnectPythonError) base.cr.timeManager.setExceptionInfo() base.cr.sendDisconnect() if hasattr(builtins, 'base'): base.destroy() self.notify.info('Exception exit.\n') import traceback traceback.print_exc() sys.exit() return def isDownloadComplete(self): return True def launcherMessage(self, msg): if msg != self.lastLauncherMsg: self.lastLauncherMsg = msg self.notify.info(msg) def isTestServer(self): return self.testServerFlag def recordPeriodTimeRemaining(self, secondsRemaining): self.setValue(self.PeriodTimeRemainingKey, int(secondsRemaining)) def recordPeriodName(self, periodName): self.setValue(self.PeriodNameKey, periodName) def recordSwid(self, swid): self.setValue(self.SwidKey, swid) def getGoUserName(self): return self.goUserName def setGoUserName(self, userName): self.goUserName = userName def setPandaWindowOpen(self): self.setValue(self.PandaWindowOpenKey, 1) def setPandaErrorCode(self, code): self.notify.info('setting panda error code to %s' % code) self.pandaErrorCode = code errorLog = open(self.errorfile, 'w') errorLog.write(str(code) + '\n') errorLog.flush() errorLog.close() def getPandaErrorCode(self): return self.pandaErrorCode def setDisconnectDetailsNormal(self): self.notify.info('Setting Disconnect Details normal') self.disconnectCode = 0 self.disconnectMsg = 'normal' def setDisconnectDetails(self, newCode, newMsg): self.notify.info('New Disconnect Details: %s - %s ' % (newCode, newMsg)) self.disconnectCode = newCode self.disconnectMsg = newMsg def setServerVersion(self, version): self.ServerVersion = version def getServerVersion(self): return self.ServerVersion def getIsNewInstallation(self): result = self.getValue(self.NewInstallationKey, 1) result = base.config.GetBool('new-installation', result) return result def setIsNotNewInstallation(self): self.setValue(self.NewInstallationKey, 0) def getLastLogin(self): return self.getValue(self.LastLoginKey, '') def setLastLogin(self, login): self.setValue(self.LastLoginKey, login) def setUserLoggedIn(self): self.setValue(self.UserLoggedInKey, '1') def setPaidUserLoggedIn(self): self.setValue(self.PaidUserLoggedInKey, '1') def getReferrerCode(self): return self.getValue(self.ReferrerKey, None) def getPhaseComplete(self, phase): return True def getPercentPhaseComplete(self, phase): return 100 def cleanup(self): self.notify.info('cleanup: cleaning up Launcher') self.ignoreAll() del self.clock del self.http def getBlue(self): return None def getPlayToken(self): return None def getDISLToken(self): DISLToken = self.getValue(self.DISLTokenKey) self.setValue(self.DISLTokenKey, '') if DISLToken == 'NO DISLTOKEN': DISLToken = None return DISLToken