API improvements

- fixed `constants` casing
- added `constants.prefix` fields;
  renamed a lot of fields;
  encoded game related names
- added `Game` class to work with game info
  added `Game.current` field to parse installed game version
This commit is contained in:
Observer KRypt0n_ 2021-12-22 00:28:58 +02:00
parent 748b197984
commit 8da7e3efcc
No known key found for this signature in database
GPG key ID: DC5D4EC1303465DA
6 changed files with 139 additions and 81 deletions

View file

@ -1,4 +1,4 @@
import Constants from './Constants';
import constants from './Constants';
import Downloader from './Downloader';
import Archive from './Archive';
@ -31,7 +31,7 @@ export default abstract class Installer
public constructor(uri: string, unpackDir: string|Promise<string>)
{
Constants.paths.launcher.then((launcherDir) => {
constants.paths.launcher.then((launcherDir) => {
const archivePath = `${launcherDir}/${Downloader.fileFromUri(uri)}`;
// Download archive

View file

@ -1,4 +1,4 @@
import Constants from './Constants';
import constants from './Constants';
declare const Neutralino;
declare const NL_CWD;
@ -18,7 +18,7 @@ export default class Configs
public static get(name: string = ''): Promise<undefined|scalar|scalar[]>
{
return new Promise(async (resolve) => {
Neutralino.filesystem.readFile(await Constants.paths.config).then((config) => {
Neutralino.filesystem.readFile(await constants.paths.config).then((config) => {
config = JSON.parse(config);
if (name !== '')
@ -50,15 +50,15 @@ export default class Configs
};
return new Promise(async (resolve) => {
Neutralino.filesystem.readFile(await Constants.paths.config).then(async (config) => {
Neutralino.filesystem.readFile(await constants.paths.config).then(async (config) => {
config = JSON.stringify(getUpdatedArray(name.split('.'), JSON.parse(config), value), null, 4);
Neutralino.filesystem.writeFile(await Constants.paths.config, config)
Neutralino.filesystem.writeFile(await constants.paths.config, config)
.then(() => resolve());
}).catch(async () => {
let config = JSON.stringify(getUpdatedArray(name.split('.'), {}, value), null, 4);
Neutralino.filesystem.writeFile(await Constants.paths.config, config)
Neutralino.filesystem.writeFile(await constants.paths.config, config)
.then(() => resolve());
});
});
@ -98,11 +98,11 @@ export default class Configs
current = JSON.stringify(updateDefaults(current, configs), null, 4);
Neutralino.filesystem.writeFile(await Constants.paths.config, current)
Neutralino.filesystem.writeFile(await constants.paths.config, current)
.then(() => resolve());
};
Neutralino.filesystem.readFile(await Constants.paths.config)
Neutralino.filesystem.readFile(await constants.paths.config)
.then((config) => setDefaults(JSON.parse(config)))
.catch(() => setDefaults({}));
});

View file

@ -1,26 +1,61 @@
import Configs from './Configs';
declare const Neutralino;
declare const NL_PATH;
class Prefix
{
/**
* Current prefix directory
*
* @default "~/.local/share/anime-game-launcher/game"
*/
public static get current(): Promise<string>
{
return new Promise(async (resolve) => resolve(await Configs.get('prefix') as string));
}
/**
* Default prefix directory
*
* @default "~/.local/share/anime-game-launcher/game"
*/
public static get default(): Promise<string>
{
return new Promise(async (resolve) => resolve(`${await Paths.launcherDir}/game`));
}
/**
* Change prefix directory
*
* @returns promise that indicates when the prefix path will be changed in configs
*/
public static set(location: string): Promise<void>
{
return Configs.set('prefix', location);
}
}
class Paths
{
/**
* Directory where the launcher's executable stored
*/
public static readonly app: string = NL_PATH;
public static readonly appDir: string = NL_PATH;
/**
* Shaders directory
*
* @defaultValue "[Constants.paths.app]/public/shaders"
* @default "[constants.paths.app]/public/shaders"
*/
public static readonly shaders: string = `${this.app}/public/shaders`;
public static readonly shadersDir: string = `${this.appDir}/public/shaders`;
/**
* Launcher data directory
*
* @defaultValue "~/.local/share/anime-game-launcher"
* @default "~/.local/share/anime-game-launcher"
*/
public static get launcher(): Promise<string>
public static get launcherDir(): Promise<string>
{
return new Promise(async (resolve) => resolve(`${await Neutralino.os.getPath('data')}/anime-game-launcher`));
}
@ -28,63 +63,70 @@ class Paths
/**
* Runners directory
*
* @defaultValue "~/.local/share/anime-game-launcher/runners"
* @default "~/.local/share/anime-game-launcher/runners"
*/
public static get runners(): Promise<string>
public static get runnersDir(): Promise<string>
{
return new Promise(async (resolve) => resolve(`${await this.launcher}/runners`));
return new Promise(async (resolve) => resolve(`${await this.launcherDir}/runners`));
}
/**
* DXVKs directory
*
* @defaultValue "~/.local/share/anime-game-launcher/dxvks"
* @default "~/.local/share/anime-game-launcher/dxvks"
*/
public static get dxvks(): Promise<string>
public static get dxvksDir(): Promise<string>
{
return new Promise(async (resolve) => resolve(`${await this.launcher}/dxvks`));
return new Promise(async (resolve) => resolve(`${await this.launcherDir}/dxvks`));
}
/**
* Config file
*
* @defaultValue "~/.local/share/anime-game-launcher/config.json"
* @default "~/.local/share/anime-game-launcher/config.json"
*/
public static get config(): Promise<string>
{
return new Promise(async (resolve) => resolve(`${await this.launcher}/config.json`));
return new Promise(async (resolve) => resolve(`${await this.launcherDir}/config.json`));
}
/*public static readonly prefix = new class
public static readonly prefix = Prefix;
/**
* Game directory
*
* @default "~/.local/share/anime-game-launcher/game/drive_c/Program Files/[An Anime Game]"
*
* @returns "[constants.prefix.current]/drive_c/Program Files/[An Anime Game]"
*/
public static get gameDir(): Promise<string>
{
/**
* Current prefix directory
*
* Default is ~/.local/share/anime-game-launcher/game
*
* @returns string
*/
/*public get(): string
{
return LauncherLib.getConfig('prefix');
}
return new Promise(async (resolve) => resolve(`${await this.prefix.current}/drive_c/Program Files/${constants.placeholders.uppercase.full}`));
}
public getDefault(): string
{
return path.join(os.homedir(), '.local', 'share', 'anime-game-launcher', 'game');
}
/**
* Game data directory
*
* @default "~/.local/share/anime-game-launcher/game/drive_c/Program Files/[An Anime Game]/[An Anime Game]_Data"
*
* @returns "[constants.paths.gameDir]/[An Anime Game]_Data"
*/
public static get gameDataDir(): Promise<string>
{
return new Promise(async (resolve) => resolve(`${await this.gameDir}/${constants.placeholders.uppercase.first + constants.placeholders.uppercase.second}_Data`));
}
public set(location: string)
{
if (path.relative(LauncherLib.getConfig('prefix'), location) === '')
return console.log('Can\'t set already selected prefix as new prefix');
const dataPath = path.join(location, 'drive_c', 'Program Files', constants.placeholders.uppercase.full, `${constants.placeholders.uppercase.first + constants.placeholders.uppercase.second}_Data`);
LauncherLib.updateConfig('prefix', location);
LauncherLib.updateConfig('version', LauncherLib.getGameVersion(dataPath));
}
}*/
/**
* Game voice data directory
*
* @default "~/.local/share/anime-game-launcher/game/drive_c/Program Files/[An Anime Game]/[An Anime Game]_Data/StreamingAssets/Audio/GeneratedSoundBanks/Windows"
*
* @returns "[constants.paths.gameDataDir]/StreamingAssets/Audio/GeneratedSoundBanks/Windows"
*/
public static get voiceDir(): Promise<string>
{
return new Promise(async (resolve) => resolve(`${await this.gameDataDir}/StreamingAssets/Audio/GeneratedSoundBanks/Windows`));
}
}
export default class constants
@ -92,16 +134,16 @@ export default class constants
public static readonly placeholders = {
uppercase:
{
first: 'Genshin',
second: 'Impact',
full: 'Genshin Impact',
company: 'miHoYo'
first: atob('R2Vuc2hpbg=='),
second: atob('SW1wYWN0'),
full: atob('R2Vuc2hpbiBJbXBhY3Q='),
company: atob('bWlIb1lv')
},
lowercase:
{
first: 'genshin',
company: 'mihoyo'
first: atob('Z2Vuc2hpbg=='),
company: atob('bWlob3lv')
}
};
@ -134,23 +176,8 @@ export default class constants
public static readonly runnersUri: string = `${this.uri.launcher}/raw/main/runners.json`;
public static readonly dxvksUri: string = `${this.uri.launcher}/raw/main/dxvks.json`;
/*public static get gameDir(): string
{
return path.join(this.prefixDir.get(), 'drive_c', 'Program Files', this.placeholders.uppercase.full);
}
public static get fpsunlockerDir(): string
{
return path.join(this.prefixDir.get(), 'drive_c', 'Program Files', Buffer.from('R0lfRlBTVW5sb2NrZXI=', 'base64').toString());
}
public static get voiceDir(): string
{
return path.join(this.gameDir, `${this.placeholders.uppercase.first + this.placeholders.uppercase.second}_Data`, 'StreamingAssets', 'Audio', 'GeneratedSoundBanks', 'Windows');
}
public static getPatchUri(source: 'origin' | 'additional'): string
{
return `${this.uri.patch[source]}/archive/master.zip`;
}*/
}
}

View file

@ -1,6 +1,6 @@
import type { DXVK as TDXVK } from './types/DXVK';
import Constants from './Constants';
import constants from './Constants';
import AbstractInstaller from './AbstractInstaller';
declare const Neutralino;
@ -9,7 +9,7 @@ class Stream extends AbstractInstaller
{
public constructor(dxvk: TDXVK)
{
super(dxvk.uri, Constants.paths.dxvks);
super(dxvk.uri, constants.paths.dxvksDir);
}
}
@ -21,8 +21,8 @@ export default class DXVK
public static get(): Promise<TDXVK[]>
{
return new Promise((resolve) => {
Constants.paths.dxvks.then(async (dxvksDir: string) => {
let list: TDXVK[] = JSON.parse(await Neutralino.filesystem.readFile(`${Constants.paths.app}/public/dxvks.json`));
constants.paths.dxvksDir.then(async (dxvksDir: string) => {
let list: TDXVK[] = JSON.parse(await Neutralino.filesystem.readFile(`${constants.paths.appDir}/public/dxvks.json`));
const installed: { entry: string, type: string }[] = await Neutralino.filesystem.readDirectory(dxvksDir);
@ -47,7 +47,7 @@ export default class DXVK
}
/**
* Download DXVK to the [Constants.paths.dxvks] directory
* Download DXVK to the [constants.paths.dxvks] directory
*
* @param dxvk DXVK object or version
* @returns null if the DXVK with specified version is not exists. Otherwise - installation stream

31
src/ts/Game.ts Normal file
View file

@ -0,0 +1,31 @@
import constants from './Constants';
declare const Neutralino;
export default class Game
{
/**
* Get current installed game version
*
* @returns null if the game version can't be parsed
*/
public static get current(): Promise<string|null>
{
return new Promise(async (resolve) => {
const persistentPath = `${await constants.paths.gameDataDir}/Persistent/ScriptVersion`;
const globalGameManagersPath = `${await constants.paths.gameDataDir}/globalgamemanagers`;
Neutralino.filesystem.readFile(persistentPath)
.then((version) => resolve(version))
.catch(() => {
Neutralino.filesystem.readFile(globalGameManagersPath)
.then((config) => {
const version = /([1-9]+\.[0-9]+\.[0-9]+)_[\d]+_[\d]+/.exec(config);
resolve(version !== null ? version[1] : null);
})
.catch(() => resolve(null));
});
});
}
}

View file

@ -3,7 +3,7 @@ import {
RunnerFamily
} from './types/Runners';
import Constants from './Constants';
import constants from './Constants';
import AbstractInstaller from './AbstractInstaller';
declare const Neutralino;
@ -12,7 +12,7 @@ class Stream extends AbstractInstaller
{
public constructor(runner: Runner)
{
super(runner.uri, Constants.paths.runners);
super(runner.uri, constants.paths.runnersDir);
}
}
@ -24,8 +24,8 @@ class Runners
public static get(): Promise<RunnerFamily[]>
{
return new Promise((resolve) => {
Constants.paths.runners.then(async (runnersDir: string) => {
let list: RunnerFamily[] = JSON.parse(await Neutralino.filesystem.readFile(`${Constants.paths.app}/public/runners.json`));
constants.paths.runnersDir.then(async (runnersDir: string) => {
let list: RunnerFamily[] = JSON.parse(await Neutralino.filesystem.readFile(`${constants.paths.appDir}/public/runners.json`));
const installed: { entry: string, type: string }[] = await Neutralino.filesystem.readDirectory(runnersDir);
@ -59,7 +59,7 @@ class Runners
}
/**
* Download runner to the [Constants.paths.runners] directory
* Download runner to the [constants.paths.runners] directory
*
* @param runner runner object or name
* @returns null if the runner with specified name is not exists. Otherwise - installation stream