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';
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());
}
}
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){
await update();
}
//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.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<string[]>{
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<any> {
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<boolean>{
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<number>{
return new Promise((res, rej) => {
dialog.showMessageBox(options, (index) => {
res(index);
})
});
}
const default_server_config = '<?xml version="1.0"?>\
<configuration>\
<option name="updateType" value="1"/>\
<list name="player"/>\
</configuration>';
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<string>{
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));
});
});
}