mirror of
https://github.com/an-anime-team/an-anime-game-launcher.git
synced 2024-12-24 10:38:14 +03:00
API improvements
- added `Runners.getWinetricks()` method to get the `winetricks.sh` script - added `Runners.createPrefix()` to create wine prefix using the currently selected wine version - added game installation and updating action scripts - added `Process.addSlashes()` method to easily isolate some strings
This commit is contained in:
parent
342eeadbfd
commit
e8c721dc93
6 changed files with 151 additions and 12 deletions
|
@ -22,7 +22,7 @@
|
||||||
"fullScreen": false,
|
"fullScreen": false,
|
||||||
"alwaysOnTop": false,
|
"alwaysOnTop": false,
|
||||||
"icon": "/public/icons/64x64.png",
|
"icon": "/public/icons/64x64.png",
|
||||||
"enableInspector": false,
|
"enableInspector": true,
|
||||||
"borderless": false,
|
"borderless": false,
|
||||||
"maximize": false,
|
"maximize": false,
|
||||||
"hidden": true,
|
"hidden": true,
|
||||||
|
|
|
@ -7,8 +7,6 @@ import Configs from './Configs';
|
||||||
import ProgressBar from './launcher/ProgressBar';
|
import ProgressBar from './launcher/ProgressBar';
|
||||||
import State from './launcher/State';
|
import State from './launcher/State';
|
||||||
|
|
||||||
declare const Neutralino;
|
|
||||||
|
|
||||||
export default class Launcher
|
export default class Launcher
|
||||||
{
|
{
|
||||||
public state?: State;
|
public state?: State;
|
||||||
|
@ -51,7 +49,7 @@ export default class Launcher
|
||||||
public showSettings(): Promise<boolean>
|
public showSettings(): Promise<boolean>
|
||||||
{
|
{
|
||||||
return new Promise(async (resolve) => {
|
return new Promise(async (resolve) => {
|
||||||
if (this.settingsMenu && await this.settingsMenu.running())
|
if (this.settingsMenu)
|
||||||
resolve(false);
|
resolve(false);
|
||||||
|
|
||||||
else
|
else
|
||||||
|
@ -67,7 +65,7 @@ export default class Launcher
|
||||||
|
|
||||||
if (window.status)
|
if (window.status)
|
||||||
{
|
{
|
||||||
this.settingsMenu = new Process(window.data!.pid, 500);
|
this.settingsMenu = new Process(window.data!.pid, null);
|
||||||
|
|
||||||
/*this.settingsMenu.finish(() => {
|
/*this.settingsMenu.finish(() => {
|
||||||
Window.current.show();
|
Window.current.show();
|
||||||
|
|
|
@ -6,6 +6,8 @@ import type {
|
||||||
import constants from '../Constants';
|
import constants from '../Constants';
|
||||||
import Configs from '../Configs';
|
import Configs from '../Configs';
|
||||||
import AbstractInstaller from './AbstractInstaller';
|
import AbstractInstaller from './AbstractInstaller';
|
||||||
|
import Downloader from './Downloader';
|
||||||
|
import Process from '../neutralino/Process';
|
||||||
|
|
||||||
declare const Neutralino;
|
declare const Neutralino;
|
||||||
|
|
||||||
|
@ -119,6 +121,97 @@ class Runners
|
||||||
else resolve(new Stream(runner));
|
else resolve(new Stream(runner));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get path to the winetricks.sh file
|
||||||
|
*
|
||||||
|
* If this file is not downloaded - then this method will download it
|
||||||
|
* and return the path after it
|
||||||
|
*/
|
||||||
|
public static getWinetricks(): Promise<string>
|
||||||
|
{
|
||||||
|
return new Promise(async (resolve) => {
|
||||||
|
const winetricksPath = `${await constants.paths.launcherDir}/winetricks.sh`;
|
||||||
|
|
||||||
|
Neutralino.filesystem.getStats(winetricksPath)
|
||||||
|
.then(() => resolve(winetricksPath))
|
||||||
|
.catch(() => {
|
||||||
|
Downloader.download(constants.uri.winetricks, winetricksPath).then((stream) => {
|
||||||
|
stream.finish(() => resolve(winetricksPath));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create wine prefix using the current selected wine
|
||||||
|
*
|
||||||
|
* @param path folder to create prefix in
|
||||||
|
* @param progress function that will be called with every creation step
|
||||||
|
*
|
||||||
|
* @returns false if there's no selected wine version. Otherwise true
|
||||||
|
*/
|
||||||
|
public static createPrefix(path: string, progress?: (output: string, current: number, total: number) => void): Promise<boolean>
|
||||||
|
{
|
||||||
|
const installationSteps = [
|
||||||
|
// corefonts
|
||||||
|
'Executing w_do_call corefonts',
|
||||||
|
'Executing load_corefonts',
|
||||||
|
'Executing load_andale',
|
||||||
|
'Executing load_arial',
|
||||||
|
'Executing load_comicsans',
|
||||||
|
'Executing load_courier',
|
||||||
|
'Executing load_georgia',
|
||||||
|
'Executing load_impact',
|
||||||
|
'Executing load_times',
|
||||||
|
'Executing load_trebuchet',
|
||||||
|
'Executing load_verdana',
|
||||||
|
'Executing load_webdings',
|
||||||
|
|
||||||
|
// usetakefocus=n (fullscreen input issues fix)
|
||||||
|
'Executing load_usetakefocus n'
|
||||||
|
];
|
||||||
|
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
this.current.then((runner) => {
|
||||||
|
if (runner === null)
|
||||||
|
resolve(false);
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.getWinetricks().then(async (winetricks) => {
|
||||||
|
// let installationProgress = 0;
|
||||||
|
|
||||||
|
const process = await Process.run(`bash '${Process.addSlashes(winetricks)}' corefonts usetakefocus=n`, {
|
||||||
|
env: {
|
||||||
|
WINE: `${await constants.paths.runnersDir}/${runner.name}/${runner.files.wine}`,
|
||||||
|
WINESERVER: `${await constants.paths.runnersDir}/${runner.name}/${runner.files.wineserver}`,
|
||||||
|
WINEPREFIX: path
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// todo: add process output reading
|
||||||
|
|
||||||
|
process.finish(() => resolve(true));
|
||||||
|
|
||||||
|
/*installerProcess.stdout.on('data', (data: string) => {
|
||||||
|
let str = data.toString();
|
||||||
|
|
||||||
|
for (let i = 0; i < installationSteps.length; ++i)
|
||||||
|
if (str.includes(installationSteps[i]))
|
||||||
|
{
|
||||||
|
installationProgress = i + 1;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
progress(str, installationProgress, installationSteps.length);
|
||||||
|
});*/
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Runners;
|
export default Runners;
|
||||||
|
|
|
@ -11,7 +11,10 @@ export default class State
|
||||||
protected _state: LauncherState = 'game-launch-available';
|
protected _state: LauncherState = 'game-launch-available';
|
||||||
|
|
||||||
protected events = {
|
protected events = {
|
||||||
'game-launch-available': import('./states/Launch')
|
'game-launch-available': import('./states/Launch'),
|
||||||
|
|
||||||
|
'game-install-available': import('./states/Install'),
|
||||||
|
'game-update-available': import('./states/Install')
|
||||||
};
|
};
|
||||||
|
|
||||||
public constructor(launcher: Launcher)
|
public constructor(launcher: Launcher)
|
||||||
|
|
39
src/ts/launcher/states/Install.ts
Normal file
39
src/ts/launcher/states/Install.ts
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
import type Launcher from '../../Launcher';
|
||||||
|
|
||||||
|
import Game from '../../Game';
|
||||||
|
|
||||||
|
export default (launcher: Launcher): Promise<void> => {
|
||||||
|
return new Promise(async (resolve) => {
|
||||||
|
Game.update(await Game.current).then((stream) => {
|
||||||
|
launcher.progressBar?.init({
|
||||||
|
label: 'Downloading game...',
|
||||||
|
showSpeed: true,
|
||||||
|
showEta: true,
|
||||||
|
showPercents: true,
|
||||||
|
showTotals: true
|
||||||
|
});
|
||||||
|
|
||||||
|
stream?.downloadStart(() => launcher.progressBar?.show());
|
||||||
|
|
||||||
|
stream?.downloadProgress((current: number, total: number, difference: number) => {
|
||||||
|
launcher.progressBar?.update(current, total, difference);
|
||||||
|
});
|
||||||
|
|
||||||
|
stream?.unpackStart(() => {
|
||||||
|
launcher.progressBar?.init({
|
||||||
|
label: 'Unpacking game...',
|
||||||
|
showSpeed: true,
|
||||||
|
showEta: true,
|
||||||
|
showPercents: true,
|
||||||
|
showTotals: true
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
stream?.unpackProgress((current: number, total: number, difference: number) => {
|
||||||
|
launcher.progressBar?.update(current, total, difference);
|
||||||
|
});
|
||||||
|
|
||||||
|
stream?.unpackFinish(() => resolve());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
|
@ -117,22 +117,19 @@ class Process
|
||||||
*/
|
*/
|
||||||
public static run(command: string, options: ProcessOptions = {}): Promise<Process>
|
public static run(command: string, options: ProcessOptions = {}): Promise<Process>
|
||||||
{
|
{
|
||||||
// Replace '\a\b' to '\\a\\b'
|
|
||||||
// And replace ''' to '\''
|
|
||||||
const addSlashes = (str: string) => str.replaceAll('\\', '\\\\').replaceAll('\'', '\\\'');
|
|
||||||
|
|
||||||
return new Promise(async (resolve) => {
|
return new Promise(async (resolve) => {
|
||||||
// Set env variables
|
// Set env variables
|
||||||
if (options.env)
|
if (options.env)
|
||||||
{
|
{
|
||||||
Object.keys(options.env).forEach((key) => {
|
Object.keys(options.env).forEach((key) => {
|
||||||
command = `${key}='${addSlashes(options.env![key])}' ${command}`;
|
command = `${key}='${this.addSlashes(options.env![key])}' ${command}`;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set current working directory
|
// Set current working directory
|
||||||
if (options.cwd)
|
if (options.cwd)
|
||||||
command = `cd '${addSlashes(options.cwd)}' && ${command} && cd -`;
|
command = `cd '${this.addSlashes(options.cwd)}' && ${command} && cd -`;
|
||||||
|
|
||||||
// And run the command
|
// And run the command
|
||||||
const process = await Neutralino.os.execCommand(command, {
|
const process = await Neutralino.os.execCommand(command, {
|
||||||
|
@ -143,6 +140,15 @@ class Process
|
||||||
resolve(new Process(process.pid));
|
resolve(new Process(process.pid));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace '\a\b' to '\\a\\b'
|
||||||
|
* And replace ''' to '\''
|
||||||
|
*/
|
||||||
|
public static addSlashes(str: string): string
|
||||||
|
{
|
||||||
|
return str.replaceAll('\\', '\\\\').replaceAll('\'', '\\\'');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type { ProcessOptions };
|
export type { ProcessOptions };
|
||||||
|
|
Loading…
Reference in a new issue