import { ManaPlusApp } from './manaApp/manaApp.interface'; import { ManaPlusAppWindows } from './manaApp/windows'; import * as os from 'os'; import * as path from 'path'; import * as fs from 'fs-extra'; import { app, ipcMain, shell, dialog } from 'electron'; import { Status, EventEmitter } from '../status'; import { ManaPlusAppLinux } from './manaApp/linux'; let ManaPlusInstance:ManaPlusApp; let CurrentServer:{serverID:string,address:string}=null; export namespace ManaPlus{ export const ERRORS = { NOT_INITILIZED_YET_ERROR:new Error("The ManaPlus updater wasn't initilized") } export function init(){ if(os.platform() == "win32"){ ManaPlusInstance = new ManaPlusAppWindows(); console.log("GameDir:"+ManaPlusInstance.getGameDir()); } if(os.platform() == "linux"){ ManaPlusInstance = new ManaPlusAppLinux(); console.log("startCommand:"+ManaPlusInstance.startCommand); } } export async function update(){ if(!wasInitilized())throw ERRORS.NOT_INITILIZED_YET_ERROR; return await ManaPlusInstance.update(); } export async function start(args: any){ CurrentServer={ serverID:args.serverID, address:args.address }; let params:string[]; try { params = await makeParams(args.address,args.port,args.engine,args.username,args.password); //params = ['-v'];// DEBUG: This option is to disable manaplus for testing (open it just for getting the version) } catch (e){ console.log(e); Status.showError("Launch Preperation Failed (LPF_PARMS)", e.message, "Launch preparation failed"); Status.setPlaying(false); return; } let willUpdate:boolean=false; // check if it is installed if(ManaPlusInstance.isInstalled()){ // Check if update is available and ask if the user wants to update try { let version = await ManaPlusInstance.updateAvailable(); willUpdate = (version.isNewVersion && await updateDialog(version.newestVersion)); } catch (e){ console.log(e); Status.showError("Launch Preperation Failed (LPF_Update): This error can also mean that you are offline, \ please check you network connection first.", e.message, "Launch preparation failed") Status.setPlaying(false); return; } } else { // Not installed will install it willUpdate = true; } // Install/Update the gameclient if needed if(willUpdate){ try { await update(); } catch (error) { Status.setPlaying(false); throw error; } } //IDEA have client data updated here to, if needed // Run it Status.setGameRunning(true); EventEmitter.emit('closeWindow'); EventEmitter.emit('openTray'); await runManaProgram(params,ManaPlusInstance.startCommand,args.address); // On Close Status.setGameStatus({server: "Launcher"}) Status.setGameRunning(false); Status.setPlaying(false); Status.removeActivity(); EventEmitter.emit('reopenWindow'); EventEmitter.emit('closeTray'); CurrentServer=null; } } ipcMain.on('getScreenshots', (event:any, arg:string)=> { const screenshotsDir = path.normalize(app.getPath('userData')+`/screenshots/${arg}/`); fs.existsSync(screenshotsDir) || fs.mkdirSync(screenshotsDir); fs.readdir(screenshotsDir, (err, dir) => { let screenshots:string[]=[]; for (var i = 0, path; path = dir[i]; i++) { screenshots.push(path); } event.sender.send('getScreenshots', {dir:screenshotsDir, screenshots:screenshots.reverse().slice(0, 24)}); }); }); EventEmitter.on('Mana:openScreenshotDir', ()=>{ shell.openItem(path.normalize(app.getPath('userData')+`/screenshots/${CurrentServer.address}/`)); }); function wasInitilized(){ return typeof(ManaPlusInstance) !== "undefined" && typeof(ManaPlusInstance) !== "undefined"; } async function makeParams(server: any,port: any,engine: any,username?: any,password?: any):Promise{ let parameters:string[] = []; if(server && engine && port && server != 'noServer'){ parameters.push(...[ "-s", server, "-y", engine, "-p", port ]); if(username && password){ parameters.push(...[ "-U", username, "-P", password ]); } } // Setup Paths and stuff const configDir = path.normalize(app.getPath('userData')+"/mana_config"); const localDataDir = path.normalize(app.getPath('userData')+"/mana_local_data"); const screenshotsDir = path.normalize(app.getPath('userData')+`/screenshots/${server}`); await fs.ensureDir(configDir); await fs.ensureDir(localDataDir); await fs.ensureDir(screenshotsDir); parameters.push(...[ "-C", configDir, "-L", localDataDir, "--screenshot-dir", screenshotsDir, ]); //console.log(parameters); return parameters; } let manaplusInstance: any=null; function runManaProgram(parameters: string[],gameExe:string,server?:string): Promise { return new Promise(async(resolve, reject)=>{ if(server){ Status.setActivity(`Preparing Launch`); await setSkipUpdateWindows(server); } Status.setActivity(`Starting ManaPlus`); //console.log(gameExe, parameters); const child = require('child_process').execFile(gameExe, parameters, function(err:Error, data:any) { console.log(err); console.log(data.toString()); Status.setActivity(`ManaPlus is running`); }); child.on('close', ()=>{ manaplusInstance = null; resolve(); }); child.on('error', ()=>{ manaplusInstance = null; resolve(); //// TODO: Handle Error }); manaplusInstance = child; }); } EventEmitter.on("Mana:killMana",()=>{ if(manaplusInstance && manaplusInstance !== null) manaplusInstance.kill('SIGINT'); }); async function updateDialog(newestVersion:string):Promise{ const options = { type: 'info', title: `ManaPlus Update available: ${newestVersion}`, message: "Do you want to update now? Please note that you'll have to update eventually to ensure further compability with the servers", buttons: ['Nah, LATER', 'Update NOW'] } let dialog = await dialogPromiseWrapper(options); console.log("....",dialog); return dialog === 1; } function dialogPromiseWrapper(options:any):Promise{ return new Promise((res, rej) => { dialog.showMessageBox(options, (index) => { res(index); }) }); } const default_server_config = '\ \ '; const parseString = require('xml2js').parseString, xml2js = require('xml2js'); async function setSkipUpdateWindows(server:string){ const serverConfigXML = path.normalize(app.getPath('userData')+`/mana_config/${server}/config.xml`); if(fs.existsSync(serverConfigXML)){ //add to this file try{ let data = await fs.readFile(serverConfigXML, 'utf8'); data = await editXML(data); await fs.outputFile(serverConfigXML, data); } catch (err){ console.log(err); } }else{ //create the file fs.outputFile(serverConfigXML, default_server_config); } return; } function editXML(xml:string):Promise{ return new Promise((res, rej)=>{ parseString(xml, function(err:any, result:any){ if(err) console.log(err); var json = result; const updaterVar = json.configuration.option.find((item:any)=>item.$.name=="updateType"); if(updaterVar){ if(updaterVar.$.value === 1){ return rej(new Error("Has allready the right value")); } updaterVar.$.value = 1; }else{ json.configuration.option.push({$:{name:"updateType",value:1}}); } var builder = new xml2js.Builder(); res(builder.buildObject(json)); }); }); }