summaryrefslogblamecommitdiff
path: root/src/main/manaplus/manaplus.ts
blob: 0f3f3a08e323d2a867adfd1cfcfab333a245e5ba (plain) (tree)
1
2
3
4
5
6
7
8
9


                                                          
                            
                               
                                                  

                                                   
                                                        
                                         
 
                                  
 
                                                                
 
                           
                         

                                              
     
    
 

                                   
                                                  
                                                              
     
 
                                   
                                                
                                                                   
     

   

                                                                



                                           


                                          
                           
      
                         
         






                                
                                                                                                                       
                 
                     




                                                
                               

             
                                    
                               
                                         


                                                                         
                                 
                    
                                                                               
                   
                       





                                                                                                   
                                 





                                      
                                              
                     





                                 


                                                      
 

                                


                                                                              
               
                                                 


                                 


                                      


   
                                                                      
                                                                             








                                                                                
                                                   
    
   
 
                                                 
                 
                                                                     
    
   
 




                                              

 











                                                                 
     

                          


                                                                           








                                                                                
 
 
                                 
 




                        
                                                       
                 


                                             

                                            
                                       
                           

                 





                                          






                                                  


                              
                             







                              


                                                    
   
 
                                                                      
                   



                                                                                                                                    
                                         
    


                                                                
 
 

                             



                                       


                                                     


                                       


                                       
                      

                                                            

                                                 
                   

                       
          






                                                          











                                                                
         



                                                                                
 

                                         


       
import { ManaPlusApp } from "./manaApp/manaApp.interface";
import { ManaPlusAppWindows } from "./manaApp/windows";
import * as os from "os";
import { join } from "path";
import * as fs from "fs-extra";
import { ipcMain, shell, dialog } from "electron";
import { Status, EventEmitter } from "../status";
import { ManaPlusAppLinux } from "./manaApp/linux";
import { getUserDataPath } from "../util/app_constants";
import { execFile } from "child_process";

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();
        // console.log({version})
        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.handle("getScreenshots", async (_event: any, arg: string) => {
  const screenshotsDir = join(getUserDataPath(), "/screenshots/", `${arg}/`);
  (await fs.existsSync(screenshotsDir)) || (await fs.mkdirSync(screenshotsDir));
  const dir = await fs.readdir(screenshotsDir);

  let screenshots: string[] = [];
  for (var i = 0, path; (path = dir[i]); i++) {
    screenshots.push(path);
  }
  return {
    dir: screenshotsDir,
    screenshots: screenshots.reverse().slice(0, 24)
  };
});

EventEmitter.on("Mana:openScreenshotDir", () => {
  shell.openPath(
    join(getUserDataPath(), `/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 = join(getUserDataPath(), "/mana_config");
  const localDataDir = join(getUserDataPath(), "/mana_local_data");
  const screenshotsDir = join(getUserDataPath(), `/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<void>(async (resolve, reject) => {
    if (server) {
      Status.setActivity(`Preparing Launch`);
      await setSkipUpdateWindows(server);
    }
    Status.setActivity(`Starting ManaPlus`);

    //console.log(gameExe, parameters);
    const child = execFile(
      gameExe,
      parameters,
      {
        env: {
          ...process.env,
          APPIMAGELAUNCHER_DISABLE: "true"
        }
      },
      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 { response } = await dialog.showMessageBox(null, options);
  console.log("....", response);
  return response === 1;
}

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 = join(
    getUserDataPath(),
    `/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));
    });
  });
}