Merge remote-tracking branch 'original/main' into term

This commit is contained in:
Maroxy 2021-10-24 10:35:58 +02:00
commit a7a208645a
24 changed files with 329 additions and 333 deletions

View file

@ -98,9 +98,7 @@ app.whenReady().then(() => {
mainWindow.webContents.send('updateVP', { 'oldvp': args.oldvp });
});
ipcMain.on('rpcstate', (event, args) => {
mainWindow.webContents.send('rpcstate', {});
});
ipcMain.on('rpc-toggle', () => mainWindow.webContents.send('rpc-toggle'));
});
// Quit when all windows are closed, except on macOS. There, it's common

View file

@ -13,7 +13,7 @@
"GameDownloaded": "Spiel würde erfolgreich heruntergeladen",
"ApplyPatch": "Patch wird angewendet",
"PatchRequired": "Patch nicht verfügbar",
"PatchRequiredHint": "Diese Spielversion hat noch kein anti-cheat patch, Bitte warten sie ein paar Tage bevor sie es erneut versuchen.",
"PatchRequiredHint": "Diese Spielversion hat noch kein anti-cheat patch, Bitte warten sie ein paar Tage bevor sie es erneut versuchen",
"TestPatch": "Test Patch anwenden",
"TestPatchHint": "Diese Spielversion hat ein anti-cheat patch aber es befindet sich noch in der Testphase. Sie können noch ein paar Tage warten bis es Stabil ist oder auf eigenen Risiko den Testpatch anwenden."
"TestPatchHint": "Diese Spielversion hat ein anti-cheat patch aber es befindet sich noch in der Testphase. Sie können noch ein paar Tage warten bis es Stabil ist oder auf eigenen Risiko den Testpatch anwenden"
}

View file

@ -13,7 +13,7 @@
"GameDownloaded": "Game was successfully installed",
"ApplyPatch": "Applying patch...",
"PatchRequired": "Patch required",
"PatchRequiredHint": "This game version doesn't have an anti-cheat patch. Please, wait a few days and try again.",
"PatchRequiredHint": "This game version doesn't have an anti-cheat patch. Please, wait a few days and try again",
"TestPatch": "Apply test patch",
"TestPatchHint": "This game version has an anti-cheat patch, but it is in the testing phase. You can wait a few days until it is stable or apply it at your own risk."
"TestPatchHint": "This game version has an anti-cheat patch, but it is in the testing phase. You can wait a few days until it is stable or apply it at your own risk"
}

View file

@ -13,7 +13,7 @@
"GameDownloaded": "Game was successfully installed",
"ApplyPatch": "Applying patch...",
"PatchRequired": "Patch required",
"PatchRequiredHint": "This game version doesn't have an anti-cheat patch. Please, wait a few days and try again.",
"PatchRequiredHint": "This game version doesn't have an anti-cheat patch. Please, wait a few days and try again",
"TestPatch": "Apply test patch",
"TestPatchHint": "This game version has an anti-cheat patch, but it is in the testing phase. You can wait a few days until it is stable or apply it at your own risk."
"TestPatchHint": "This game version has an anti-cheat patch, but it is in the testing phase. You can wait a few days until it is stable or apply it at your own risk"
}

View file

@ -13,7 +13,7 @@
"GameDownloaded": "Game was successfully installed",
"ApplyPatch": "Applying patch...",
"PatchRequired": "Patch required",
"PatchRequiredHint": "This game version doesn't have an anti-cheat patch. Please, wait a few days and try again.",
"PatchRequiredHint": "This game version doesn't have an anti-cheat patch. Please, wait a few days and try again",
"TestPatch": "Apply test patch",
"TestPatchHint": "This game version has an anti-cheat patch, but it is in the testing phase. You can wait a few days until it is stable or apply it at your own risk."
"TestPatchHint": "This game version has an anti-cheat patch, but it is in the testing phase. You can wait a few days until it is stable or apply it at your own risk"
}

View file

@ -13,7 +13,7 @@
"GameDownloaded": "Game was successfully installed",
"ApplyPatch": "Applying patch...",
"PatchRequired": "Patch required",
"PatchRequiredHint": "This game version doesn't have an anti-cheat patch. Please, wait a few days and try again.",
"PatchRequiredHint": "This game version doesn't have an anti-cheat patch. Please, wait a few days and try again",
"TestPatch": "Apply test patch",
"TestPatchHint": "This game version has an anti-cheat patch, but it is in the testing phase. You can wait a few days until it is stable or apply it at your own risk."
"TestPatchHint": "This game version has an anti-cheat patch, but it is in the testing phase. You can wait a few days until it is stable or apply it at your own risk"
}

View file

@ -13,7 +13,7 @@
"GameDownloaded": "Game was successfully installed",
"ApplyPatch": "Applying patch...",
"PatchRequired": "Patch required",
"PatchRequiredHint": "This game version doesn't have an anti-cheat patch. Please, wait a few days and try again.",
"PatchRequiredHint": "This game version doesn't have an anti-cheat patch. Please, wait a few days and try again",
"TestPatch": "Apply test patch",
"TestPatchHint": "This game version has an anti-cheat patch, but it is in the testing phase. You can wait a few days until it is stable or apply it at your own risk."
"TestPatchHint": "This game version has an anti-cheat patch, but it is in the testing phase. You can wait a few days until it is stable or apply it at your own risk"
}

View file

@ -13,7 +13,7 @@
"GameDownloaded": "ゲームのインストールに成功しました",
"ApplyPatch": "パッチの適用...",
"PatchRequired": "要パッチ",
"PatchRequiredHint": "このゲームバージョンにはアンチチートパッチがありません。数日待ってから再度お試しください",
"PatchRequiredHint": "このゲームバージョンにはアンチチートパッチがありません。数日待ってから再度お試しください",
"TestPatch": "テストパッチの適用",
"TestPatchHint": "このゲームバージョンにはアンチチートパッチがありますが、テスト段階にあります。安定するまで数日お待ちいただくか、ご自身の責任で適用してください"
"TestPatchHint": "このゲームバージョンにはアンチチートパッチがありますが、テスト段階にあります。安定するまで数日お待ちいただくか、ご自身の責任で適用してください"
}

View file

@ -13,7 +13,7 @@
"GameDownloaded": "Game was successfully installed",
"ApplyPatch": "Applying patch...",
"PatchRequired": "Patch required",
"PatchRequiredHint": "This game version doesn't have an anti-cheat patch. Please, wait a few days and try again.",
"PatchRequiredHint": "This game version doesn't have an anti-cheat patch. Please, wait a few days and try again",
"TestPatch": "Apply test patch",
"TestPatchHint": "This game version has an anti-cheat patch, but it is in the testing phase. You can wait a few days until it is stable or apply it at your own risk."
"TestPatchHint": "This game version has an anti-cheat patch, but it is in the testing phase. You can wait a few days until it is stable or apply it at your own risk"
}

View file

@ -13,7 +13,7 @@
"GameDownloaded": "Game was successfully installed",
"ApplyPatch": "Applying patch...",
"PatchRequired": "Patch required",
"PatchRequiredHint": "This game version doesn't have an anti-cheat patch. Please, wait a few days and try again.",
"PatchRequiredHint": "This game version doesn't have an anti-cheat patch. Please, wait a few days and try again",
"TestPatch": "Apply test patch",
"TestPatchHint": "This game version has an anti-cheat patch, but it is in the testing phase. You can wait a few days until it is stable or apply it at your own risk."
"TestPatchHint": "This game version has an anti-cheat patch, but it is in the testing phase. You can wait a few days until it is stable or apply it at your own risk"
}

View file

@ -1,19 +1,19 @@
{
"Install": "Install",
"Update": "Update",
"Launch": "Launch",
"Runners": "Runners",
"Langs": "Languages",
"Voice": "Voice Pack",
"SettingsTitle": "Settings",
"GeneralSettings": "General",
"WineVersion": "Wine version",
"Downloading": "Downloading",
"Unpack": "Unpacking",
"GameDownloaded": "Game was successfully installed",
"ApplyPatch": "Applying patch...",
"PatchRequired": "Patch required",
"PatchRequiredHint": "This game version doesn't have an anti-cheat patch. Please, wait a few days and try again.",
"TestPatch": "Apply test patch",
"TestPatchHint": "This game version has an anti-cheat patch, but it is in the testing phase. You can wait a few days until it is stable or apply it at your own risk."
"Install": "Установить",
"Update": "Обновить",
"Launch": "Запустить",
"Runners": "Версии Wine",
"Langs": "Языки",
"Voice": "Озвучка",
"SettingsTitle": "Настройки",
"GeneralSettings": "Общее",
"WineVersion": "Версии Wine",
"Downloading": "Загрузка",
"Unpack": "Распаковка",
"GameDownloaded": "Игра была успешно установлена",
"ApplyPatch": "Применение патча...",
"PatchRequired": "Необходим патч",
"PatchRequiredHint": "Эта версия игры не имеет патча античита. Пожалуйста, подождите несколько дней и попробуйте снова",
"TestPatch": "Применить тестовый патч",
"TestPatchHint": "Эта версия игры имеет лишь тестовый патч античита. Вы можете подождать пару дней до того, как он станет стабильным, либо применить его на свой страх и риск"
}

View file

@ -13,7 +13,7 @@
"GameDownloaded": "Game was successfully installed",
"ApplyPatch": "Applying patch...",
"PatchRequired": "Patch required",
"PatchRequiredHint": "This game version doesn't have an anti-cheat patch. Please, wait a few days and try again.",
"PatchRequiredHint": "This game version doesn't have an anti-cheat patch. Please, wait a few days and try again",
"TestPatch": "Apply test patch",
"TestPatchHint": "This game version has an anti-cheat patch, but it is in the testing phase. You can wait a few days until it is stable or apply it at your own risk."
"TestPatchHint": "This game version has an anti-cheat patch, but it is in the testing phase. You can wait a few days until it is stable or apply it at your own risk"
}

View file

@ -13,7 +13,7 @@
"GameDownloaded": "Game was successfully installed",
"ApplyPatch": "Applying patch...",
"PatchRequired": "Patch required",
"PatchRequiredHint": "This game version doesn't have an anti-cheat patch. Please, wait a few days and try again.",
"PatchRequiredHint": "This game version doesn't have an anti-cheat patch. Please, wait a few days and try again",
"TestPatch": "Apply test patch",
"TestPatchHint": "This game version has an anti-cheat patch, but it is in the testing phase. You can wait a few days until it is stable or apply it at your own risk."
"TestPatchHint": "This game version has an anti-cheat patch, but it is in the testing phase. You can wait a few days until it is stable or apply it at your own risk"
}

View file

@ -13,7 +13,7 @@
"GameDownloaded": "游戏安装成功",
"ApplyPatch": "应用补丁...",
"PatchRequired": "需要补丁",
"PatchRequiredHint": "此游戏版本没有防作弊补丁。请等待几天,然后重试",
"PatchRequiredHint": "此游戏版本没有防作弊补丁。请等待几天,然后重试",
"TestPatch": "应用测试补丁",
"TestPatchHint": "此游戏版本有防作弊补丁,但处于测试阶段。您可以等待几天直到它稳定或自担风险应用它"
"TestPatchHint": "此游戏版本有防作弊补丁,但处于测试阶段。您可以等待几天直到它稳定或自担风险应用它"
}

View file

@ -13,7 +13,7 @@
"GameDownloaded": "遊戲安裝成功",
"ApplyPatch": "Applying patch...",
"PatchRequired": "需要補丁",
"PatchRequiredHint": "此遊戲版本沒有防作弊補丁。請等待幾天,然後重試",
"PatchRequiredHint": "此遊戲版本沒有防作弊補丁。請等待幾天,然後重試",
"TestPatch": "應用測試補丁",
"TestPatchHint": "該遊戲版本有一個反作弊補丁,但處於測試階段。您可以等待幾天直到它穩定或自擔風險應用它"
"TestPatchHint": "該遊戲版本有一個反作弊補丁,但處於測試階段。您可以等待幾天直到它穩定或自擔風險應用它"
}

View file

@ -1,12 +1,13 @@
const path = require('path');
const fs = require('fs');
const discordrpc = require("discord-rpc");
const { exec } = require('child_process');
const { ipcRenderer } = require('electron');
import $ from 'cash-dom';
import { Genshinlib } from './Genshinlib';
import { LauncherUI } from './LauncherUI';
import { Genshinlib } from './lib/Genshinlib';
import { LauncherUI } from './lib/LauncherUI';
import { Tools } from './lib/Tools';
import { DiscordRPC } from './lib/DiscordRPC';
if (!fs.existsSync(Genshinlib.prefixDir))
fs.mkdirSync(Genshinlib.prefixDir, { recursive: true });
@ -21,61 +22,24 @@ $(() => {
if (Genshinlib.version !== null)
document.title = 'Genshin Impact Linux Launcher - ' + Genshinlib.version;
ipcRenderer.on('change-lang', (event: void, data: any) => {
LauncherUI.updateBackground();
LauncherUI.updateSocial();
LauncherUI.updateLang(data.lang);
});
LauncherUI.setState('game-launch-available');
LauncherUI.updateBackground();
LauncherUI.updateSocial();
let rpc: any;
ipcRenderer.on('change-lang', (event: void, data: any) => {
LauncherUI.updateLang(data.lang);
LauncherUI.updateBackground();
LauncherUI.updateSocial();
});
// FIXME
if (Genshinlib.getConfig().rpc)
{
rpc = new discordrpc.Client({ transport: 'ipc' });
rpc.login({ clientId: '901534333360304168' }).catch(console.error);
if (Genshinlib.getConfig('rpc'))
DiscordRPC.init();
rpc.on('ready', () => {
rpc.setActivity({
details: 'Preparing to launch',
largeImageKey: 'launcher',
largeImageText: 'An Anime Game Launcher',
instance: false,
});
});
}
// FIXME
ipcRenderer.on('rpcstate', (event: void, data: any) => {
if(!rpc) {
rpc = new discordrpc.Client({ transport: "ipc" });
rpc.login({ clientId: '901534333360304168' }).catch(console.error);
rpc.on('ready', () => {
rpc.setActivity({
details: `Preparing to launch`,
largeImageKey: `launcher`,
largeImageText: `An Anime Game Launcher`,
instance: false,
});
});
if (!Genshinlib.getConfig().rpc)
Genshinlib.updateConfig({
rpc: true
});
} else {
rpc.clearActivity();
rpc.destroy();
rpc = false;
Genshinlib.updateConfig({
rpc: false
});
}
ipcRenderer.on('rpc-toggle', () => {
DiscordRPC.isActive() ?
DiscordRPC.init() :
DiscordRPC.close();
});
// FIXME
@ -113,14 +77,14 @@ $(() => {
console.log(`%c> Downloading voice data...`, 'font-size: 16px');
// For some reason this keeps breaking and locking up most of the time.
Genshinlib.downloadFile(voicePack.path, path.join(Genshinlib.launcherDir, voicePack.name), (current: number, total: number, difference: number) => {
Tools.downloadFile(voicePack.path, path.join(Genshinlib.launcherDir, voicePack.name), (current: number, total: number, difference: number) => {
LauncherUI.updateProgressBar(LauncherUI.i18n.translate('Downloading'), current, total, difference);
}).then(() => {
console.log(`%c> Unpacking voice data...`, 'font-size: 16px');
LauncherUI.initProgressBar();
Genshinlib.unzip(path.join(Genshinlib.launcherDir, voicePack.name), Genshinlib.gameDir, (current: number, total: number, difference: number) => {
Tools.unzip(path.join(Genshinlib.launcherDir, voicePack.name), Genshinlib.gameDir, (current: number, total: number, difference: number) => {
LauncherUI.updateProgressBar(LauncherUI.i18n.translate('Unpack'), current, total, difference);
}).then(() => {
fs.unlinkSync(path.join(Genshinlib.launcherDir, voicePack.name));
@ -136,7 +100,7 @@ $(() => {
LauncherUI.setState(Genshinlib.version === null ? 'game-installation-available' : 'game-update-available');
// Patch version is incorrect
else if (Genshinlib.getConfig().patch && Genshinlib.getConfig().patch.version != Genshinlib.getPatchInfo().version)
else if (Genshinlib.getConfig('patch') && Genshinlib.getConfig('patch.version') != Genshinlib.getPatchInfo().version)
{
// Patch is not available
if (Genshinlib.getPatchInfo().version !== data.game.latest.version)
@ -164,7 +128,7 @@ $(() => {
// Current patch is in testing phase,
// but stable is available
else if (Genshinlib.getConfig().patch && Genshinlib.getConfig().patch.version == Genshinlib.getPatchInfo().version && Genshinlib.getConfig().patch.state == 'testing' && Genshinlib.getPatchInfo().state == 'stable')
else if (Genshinlib.getConfig('patch') && Genshinlib.getConfig('patch.version') == Genshinlib.getPatchInfo().version && Genshinlib.getConfig('patch.state') == 'testing' && Genshinlib.getPatchInfo().state == 'stable')
{
console.log(`%c> Applying patch...`, 'font-size: 16px');
@ -219,12 +183,12 @@ $(() => {
{
let wineExeutable = 'wine';
if (Genshinlib.getConfig().runner !== null)
if (Genshinlib.getConfig('runner') !== null)
{
wineExeutable = path.join(
Genshinlib.runnersDir,
Genshinlib.getConfig().runner?.folder,
Genshinlib.getConfig().runner?.executable
Genshinlib.getConfig('runner.folder'),
Genshinlib.getConfig('runner.executable')
);
if (!fs.existsSync(wineExeutable))
@ -239,15 +203,12 @@ $(() => {
console.log(`Wine executable: ${wineExeutable}`);
// FIXME
if (rpc)
if (DiscordRPC.isActive())
{
rpc.setActivity({
details: `In-Game`,
largeImageKey: `game`,
largeImageText: `An Anime Game Launcher`,
startTimestamp: parseInt(new Date().setDate(new Date().getDate()).toString()),
instance: false,
DiscordRPC.setActivity({
details: 'In-Game',
largeImageKey: 'game',
largeImageText: 'An Anime Game Launcher'
});
}
@ -262,14 +223,12 @@ $(() => {
ipcRenderer.invoke('show-window');
// FIXME
if (rpc)
if (DiscordRPC.isActive())
{
rpc.setActivity({
details: `Preparing to launch`,
largeImageKey: `launcher`,
largeImageText: `An Anime Game Launcher`,
instance: false,
DiscordRPC.setActivity({
details: 'Preparing to launch',
largeImageKey: 'launcher',
largeImageText: 'An Anime Game Launcher'
});
}
@ -322,7 +281,7 @@ $(() => {
LauncherUI.initProgressBar();
Genshinlib.downloadFile(diff.path, path.join(Genshinlib.launcherDir, diff.name), (current: number, total: number, difference: number) => {
Tools.downloadFile(diff.path, path.join(Genshinlib.launcherDir, diff.name), (current: number, total: number, difference: number) => {
LauncherUI.updateProgressBar(LauncherUI.i18n.translate('Downloading'), current, total, difference);
}).then(() => {
/**
@ -336,7 +295,7 @@ $(() => {
LauncherUI.initProgressBar();
Genshinlib.unzip(path.join(Genshinlib.launcherDir, diff.name), Genshinlib.gameDir, (current: number, total: number, difference: number) => {
Tools.unzip(path.join(Genshinlib.launcherDir, diff.name), Genshinlib.gameDir, (current: number, total: number, difference: number) => {
LauncherUI.updateProgressBar(LauncherUI.i18n.translate('Unpack'), current, total, difference);
}).then(() => {
/**
@ -359,7 +318,7 @@ $(() => {
LauncherUI.initProgressBar();
Genshinlib.downloadFile(voicePack.path, path.join(Genshinlib.launcherDir, voicePack.name), (current: number, total: number, difference: number) => {
Tools.downloadFile(voicePack.path, path.join(Genshinlib.launcherDir, voicePack.name), (current: number, total: number, difference: number) => {
LauncherUI.updateProgressBar(LauncherUI.i18n.translate('Downloading'), current, total, difference);
}).then(() => {
/**
@ -370,7 +329,7 @@ $(() => {
LauncherUI.initProgressBar();
Genshinlib.unzip(path.join(Genshinlib.launcherDir, voicePack.name), Genshinlib.gameDir, (current: number, total: number, difference: number) => {
Tools.unzip(path.join(Genshinlib.launcherDir, voicePack.name), Genshinlib.gameDir, (current: number, total: number, difference: number) => {
LauncherUI.updateProgressBar(LauncherUI.i18n.translate('Unpack'), current, total, difference);
}).then(() => {
fs.unlinkSync(path.join(Genshinlib.launcherDir, voicePack.name));

46
src/ts/lib/DiscordRPC.ts Normal file
View file

@ -0,0 +1,46 @@
const discordRpc = require('discord-rpc');
export class DiscordRPC
{
protected static readonly clientId = '901534333360304168';
protected static rpc: any = null;
public static init ()
{
this.rpc = new discordRpc.Client({ transport: 'ipc' });
this.rpc.login({ clientId: this.clientId }).catch(console.error);
this.rpc.on('ready', () => {
this.rpc.setActivity({
details: 'Preparing to launch',
largeImageKey: 'launcher',
largeImageText: 'An Anime Game Launcher',
instance: false
});
});
}
public static setActivity (activity: any): void
{
this.rpc?.setActivity({
startTimestamp: parseInt(new Date().setDate(new Date().getDate()).toString()),
instance: false,
...activity
});
}
public static isActive (): boolean
{
return this.rpc !== null;
}
public static close (): void
{
this.rpc?.clearActivity();
this.rpc?.destroy();
this.rpc = null;
}
}

View file

@ -1,4 +1,5 @@
import GIJSON from './GIJSON';
import { Tools } from './Tools';
const https = require('follow-redirects').https;
@ -42,13 +43,13 @@ type Config = {
folder: string,
executable: string
},
rpc: boolean,
dxvk: string|null
dxvk: string|null,
rpc: boolean
};
export class Genshinlib
{
public static readonly patchDir: string = path.join(path.dirname(__dirname), 'patch');
public static readonly patchDir: string = path.join(path.dirname(__dirname), '..', 'patch');
public static readonly patchJson: string = path.join(this.patchDir, 'patch.json');
public static readonly patchSh = path.join(this.patchDir, 'patch.sh');
public static readonly patchAntiCrashSh = path.join(this.patchDir, 'patch_anti_logincrash.sh');
@ -71,12 +72,12 @@ export class Genshinlib
public static get version(): Config['version']
{
return this.getConfig().version;
return this.getConfig('version');
}
public static get lang(): Config['lang']
{
return this.getConfig().lang;
return this.getConfig('lang');
}
public static getRunners (): Promise<[{ title: string, runners: Runner[] }]>
@ -101,7 +102,7 @@ export class Genshinlib
// return new Promise(resolve => resolve(JSON.parse(fs.readFileSync(path.join(__dirname, '..', '..', 'dxvks.json')))));
}
public static getConfig (): Config
public static getConfig (property: string|null = null, splitProperty: boolean = true): any
{
if (!fs.existsSync(this.launcherJson))
fs.writeFileSync(this.launcherJson, JSON.stringify({
@ -119,7 +120,20 @@ export class Genshinlib
rpc: false
}, null, 4));
return JSON.parse(fs.readFileSync(this.launcherJson));
let config = JSON.parse(fs.readFileSync(this.launcherJson));
if (property === null)
return config;
else
{
if (!splitProperty)
return config[property];
property.split('.').forEach(prop => config = config[prop]);
return config;
}
}
public static setConfig (info: Config): Genshinlib
@ -158,12 +172,12 @@ export class Genshinlib
{
let background = '';
if (!this.getConfig().background.time || new Date(new Date().setHours(0,0,0,0)).setDate(new Date(new Date().setHours(0,0,0,0)).getDate()).toString() >= this.getConfig().background.time!)
if (!this.getConfig('background.time') || new Date(new Date().setHours(0,0,0,0)).setDate(new Date(new Date().setHours(0,0,0,0)).getDate()).toString() >= this.getConfig('background.time')!)
{
await fetch(this.backgroundUri + this.lang.launcher)
.then(res => res.json())
.then(async resdone => {
let prevBackground = this.getConfig().background.file;
let prevBackground = this.getConfig('background.file');
this.updateConfig({
background: {
@ -172,23 +186,23 @@ export class Genshinlib
}
});
if (fs.existsSync(path.join(this.launcherDir, this.getConfig().background.file)))
background = path.join(this.launcherDir, this.getConfig().background.file);
if (fs.existsSync(path.join(this.launcherDir, this.getConfig('background.file'))))
background = path.join(this.launcherDir, this.getConfig('background.file'));
else
{
await this.downloadFile(resdone.data.adv.background, path.join(this.launcherDir, this.getConfig().background.file), (current: number, total: number, difference: number) => null).then(() => {
await Tools.downloadFile(resdone.data.adv.background, path.join(this.launcherDir, this.getConfig('background.file')), (current: number, total: number, difference: number) => null).then(() => {
!prevBackground ?
console.log('No old background found') :
fs.unlinkSync(path.join(this.launcherDir, prevBackground));
background = path.join(this.launcherDir, this.getConfig().background.file);
background = path.join(this.launcherDir, this.getConfig('background.file'));
});
};
});
}
else background = path.join(this.launcherDir, this.getConfig().background.file);
else background = path.join(this.launcherDir, this.getConfig('background.file'));
return background;
}
@ -228,131 +242,6 @@ export class Genshinlib
});
}
public static async downloadFile (uri: string, savePath: string, progress: (current: number, total: number, difference: number) => void): Promise<void|Error>
{
return new Promise((resolve, reject) => {
https.get(uri, (response: any) => {
let length = parseInt(response.headers['content-length'], 10),
total = 0;
response.on('data', (chunk: any) => {
total += chunk.length;
progress(total, length, chunk.length);
fs.appendFileSync(savePath, chunk);
});
response.on('end', () => resolve());
}).on('error', (err: Error) => reject(err));
});
}
public static async unzip (zipPath: string, unpackedPath: string, progress: (current: number, total: number, difference: number) => void): Promise<void|Error>
{
return new Promise((resolve, reject) => {
let listenerProcess = spawn('unzip', ['-v', zipPath]),
filesList = '';
listenerProcess.stdout.on('data', (data: string) => filesList += data);
listenerProcess.on('close', () => {
let files = filesList.split(/\r\n|\r|\n/).slice(3, -3).map(line => {
line = line.trim();
if (line.slice(-1) == '/')
line = line.slice(0, -1);
let matches = /^(\d+) [a-zA-Z\:]+[ ]+(\d+)[ ]+[0-9\-]+% [0-9\-]+ [0-9\:]+ [a-f0-9]{8} (.+)/.exec(line);
if (matches)
return {
path: matches[3],
compressedSize: parseInt(matches[2]),
uncompressedSize: parseInt(matches[1])
};
});
let total = fs.statSync(zipPath)['size'], current = 0;
let unpackerProcess = spawn('unzip', ['-o', zipPath, '-d', unpackedPath]);
unpackerProcess.stdout.on('data', (data: string) => {
data.toString().split(/\r\n|\r|\n/).forEach(line => {
let items = line.split(': ');
if (items[1] !== undefined)
{
items[1] = path.relative(unpackedPath, items[1].trim());
files.forEach(file => {
if (file?.path == items[1])
{
current += file.compressedSize;
progress(current, total, file.compressedSize);
}
});
}
});
});
unpackerProcess.on('close', () => resolve());
});
});
}
public static async untar (tarPath: string, unpackedPath: string, progress: (current: number, total: number, difference: number) => void): Promise<void|Error>
{
return new Promise((resolve, reject) => {
let listenerProcess = spawn('tar', ['-tvf', tarPath]),
filesList = '', total = 0;
listenerProcess.stdout.on('data', (data: string) => filesList += data);
listenerProcess.on('close', () => {
let files = filesList.split(/\r\n|\r|\n/).slice(3, -3).map(line => {
line = line.trim();
if (line.slice(-1) == '/')
line = line.slice(0, -1);
let matches = /^[dwxr\-]+ [\w/]+[ ]+(\d+) [0-9\-]+ [0-9\:]+ (.+)/.exec(line);
// TODO: compressedSize?
if (matches)
{
total += parseInt(matches[1]);
return {
path: matches[2],
uncompressedSize: parseInt(matches[1])
};
}
});
let current = 0;
let unpackerProcess = spawn('tar', ['-xvf', tarPath, '-C', unpackedPath]);
unpackerProcess.stdout.on('data', (data: string) => {
data.toString().split(/\r\n|\r|\n/).forEach(line => {
line = line.trim();
files.forEach(file => {
if (file?.path == line)
{
current += file.uncompressedSize; // compressedSize
progress(current, total, file.uncompressedSize); // compressedSize
}
});
});
});
unpackerProcess.on('close', () => resolve());
});
});
}
// WINEPREFIX='/home/observer/genshin-impact-launcher/wineprefix' winetricks corefonts usetakefocus=n
public static async installPrefix (prefixpath: string, progress: (output: string, current: number, total: number) => void): Promise<void>
{
@ -377,13 +266,13 @@ export class Genshinlib
let installationProgress = 0;
let installerProcess;
if (this.getConfig().runner)
if (this.getConfig('runner'))
{
installerProcess = spawn('winetricks', ['corefonts', 'usetakefocus=n', 'dxvk191'], {
env: {
...process.env,
WINEPREFIX: prefixpath,
WINE: path.join(this.runnersDir, this.getConfig().runner?.folder, this.getConfig().runner?.executable)
WINE: path.join(this.runnersDir, this.getConfig('runner.folder'), this.getConfig('runner.executable'))
}
});
}
@ -421,8 +310,8 @@ export class Genshinlib
public static patchGame (version: string, onFinish: () => void, onData: (data: string) => void)
{
this.downloadFile(this.patchUri, path.join(this.launcherDir, 'krock.zip'), (current: number, total: number, difference: number) => null).then(() => {
this.unzip(path.join(this.launcherDir, 'krock.zip'), this.launcherDir, (current: number, total: number, difference: number) => null).then(() => {
Tools.downloadFile(this.patchUri, path.join(this.launcherDir, 'krock.zip'), (current: number, total: number, difference: number) => null).then(() => {
Tools.unzip(path.join(this.launcherDir, 'krock.zip'), this.launcherDir, (current: number, total: number, difference: number) => null).then(() => {
// Delete zip file and assign patch directory.
fs.unlinkSync(path.join(this.launcherDir, 'krock.zip'));
@ -476,38 +365,4 @@ export class Genshinlib
});
});
}
/*public static applyPatch (onFinish: () => void, onData: (data: string) => void)
{
let patcherProcess = spawn('bash', [Genshinlib.patchSh], {
cwd: Genshinlib.gameDir,
env: {
...process.env,
WINEPREFIX: Genshinlib.prefixDir
}
});
patcherProcess.stdout.on('data', (data: string) => onData(data));
patcherProcess.on('close', () => {
let patcherAntiCrashProcess = spawn('bash', [Genshinlib.patchAntiCrashSh], {
cwd: Genshinlib.gameDir,
env: {
...process.env,
WINEPREFIX: Genshinlib.prefixDir
}
});
patcherAntiCrashProcess.stdout.on('data', (data: string) => onData(data));
patcherAntiCrashProcess.on('close', () => {
Genshinlib.setConfig({
...Genshinlib.getConfig(),
patch: Genshinlib.getPatchInfo()
});
onFinish();
});
});
}*/
}

View file

@ -167,14 +167,14 @@ export class LauncherUI
public static updateSocial (): void
{
fetch(`https://genshin.mihoyo.com/launcher/10/${Genshinlib.lang.launcher}?api_url=https%3A%2F%2Fapi-os-takumi.mihoyo.com%2Fhk4e_global&prev=false`)
.then(res => res.text())
.then(body => {
$('#__layout').remove();
$(body).find('#__layout').appendTo('#launchcontent');
.then(res => res.text())
.then(body => {
$('#__layout').remove();
$(body).find('#__layout').appendTo('#launchcontent');
$('#launchcontent .home__main .home-swiper-wrap').remove();
$('#launchcontent .home__main .home-news').remove();
});
$('#launchcontent .home__main .home-swiper-wrap').remove();
$('#launchcontent .home__main .home-news').remove();
});
}
public static updateLang (lang: string|null = null): void

133
src/ts/lib/Tools.ts Normal file
View file

@ -0,0 +1,133 @@
const https = require('follow-redirects').https;
const fs = require('fs');
const path = require('path');
const { spawn } = require('child_process');
export class Tools
{
public static async downloadFile (uri: string, savePath: string, progress: (current: number, total: number, difference: number) => void): Promise<void|Error>
{
return new Promise((resolve, reject) => {
https.get(uri, (response: any) => {
let length = parseInt(response.headers['content-length'], 10),
total = 0;
response.on('data', (chunk: any) => {
total += chunk.length;
progress(total, length, chunk.length);
fs.appendFileSync(savePath, chunk);
});
response.on('end', () => resolve());
}).on('error', (err: Error) => reject(err));
});
}
public static async unzip (zipPath: string, unpackedPath: string, progress: (current: number, total: number, difference: number) => void): Promise<void|Error>
{
return new Promise((resolve, reject) => {
let listenerProcess = spawn('unzip', ['-v', zipPath]),
filesList = '';
listenerProcess.stdout.on('data', (data: string) => filesList += data);
listenerProcess.on('close', () => {
let files = filesList.split(/\r\n|\r|\n/).slice(3, -3).map(line => {
line = line.trim();
if (line.slice(-1) == '/')
line = line.slice(0, -1);
let matches = /^(\d+) [a-zA-Z\:]+[ ]+(\d+)[ ]+[0-9\-]+% [0-9\-]+ [0-9\:]+ [a-f0-9]{8} (.+)/.exec(line);
if (matches)
return {
path: matches[3],
compressedSize: parseInt(matches[2]),
uncompressedSize: parseInt(matches[1])
};
});
let total = fs.statSync(zipPath)['size'], current = 0;
let unpackerProcess = spawn('unzip', ['-o', zipPath, '-d', unpackedPath]);
unpackerProcess.stdout.on('data', (data: string) => {
data.toString().split(/\r\n|\r|\n/).forEach(line => {
let items = line.split(': ');
if (items[1] !== undefined)
{
items[1] = path.relative(unpackedPath, items[1].trim());
files.forEach(file => {
if (file?.path == items[1])
{
current += file.compressedSize;
progress(current, total, file.compressedSize);
}
});
}
});
});
unpackerProcess.on('close', () => resolve());
});
});
}
public static async untar (tarPath: string, unpackedPath: string, progress: (current: number, total: number, difference: number) => void): Promise<void|Error>
{
return new Promise((resolve, reject) => {
let listenerProcess = spawn('tar', ['-tvf', tarPath]),
filesList = '', total = 0;
listenerProcess.stdout.on('data', (data: string) => filesList += data);
listenerProcess.on('close', () => {
let files = filesList.split(/\r\n|\r|\n/).slice(3, -3).map(line => {
line = line.trim();
if (line.slice(-1) == '/')
line = line.slice(0, -1);
let matches = /^[dwxr\-]+ [\w/]+[ ]+(\d+) [0-9\-]+ [0-9\:]+ (.+)/.exec(line);
// TODO: compressedSize?
if (matches)
{
total += parseInt(matches[1]);
return {
path: matches[2],
uncompressedSize: parseInt(matches[1])
};
}
});
let current = 0;
let unpackerProcess = spawn('tar', ['-xvf', tarPath, '-C', unpackedPath]);
unpackerProcess.stdout.on('data', (data: string) => {
data.toString().split(/\r\n|\r|\n/).forEach(line => {
line = line.trim();
files.forEach(file => {
if (file?.path == line)
{
current += file.uncompressedSize; // compressedSize
progress(current, total, file.uncompressedSize); // compressedSize
}
});
});
});
unpackerProcess.on('close', () => resolve());
});
});
}
}

View file

@ -3,6 +3,8 @@ const fs = require('fs');
export class i18n
{
public static readonly localesDir = path.join(path.dirname(__dirname), '..', 'locales');
public static loadedLanguage: any;
public static translate (phrase: string)
@ -36,8 +38,8 @@ export class i18n
break;
}
i18n.loadedLanguage = JSON.parse(fs.readFileSync(path.join(path.dirname(__dirname), 'locales',
fs.existsSync(path.join(path.dirname(__dirname), 'locales', lang + '.json')) ?
i18n.loadedLanguage = JSON.parse(fs.readFileSync(path.join(this.localesDir,
fs.existsSync(path.join(this.localesDir, lang + '.json')) ?
lang + '.json' : 'en.json'
)));
}

View file

@ -4,8 +4,10 @@ const { ipcRenderer } = require('electron');
const { exec } = require('child_process');
import $ from 'cash-dom';
import { Genshinlib } from './Genshinlib';
import { LauncherUI } from './LauncherUI';
import { i18n } from './lib/i18n';
import { Genshinlib } from './lib/Genshinlib';
import { LauncherUI } from './lib/LauncherUI';
import { Tools } from './lib/Tools';
$(() => {
@ -31,10 +33,16 @@ $(() => {
$(`#voice-list option[value="${Genshinlib.lang.voice}"]`).prop('selected', true);
$(`#language-list option[value="${Genshinlib.lang.launcher}"]`).prop('selected', true);
if (Genshinlib.getConfig().rpc)
$(`#drpc`).prop('checked', true);
if (Genshinlib.getConfig('rpc'))
$('#drpc').prop('checked', true);
$('#drpc').on('change', () => ipcRenderer.send('rpcstate', {}));
$('#drpc').on('change', () => {
Genshinlib.updateConfig({
rpc: $('#drpc').prop('checked')
});
ipcRenderer.send('rpc-toggle');
});
$('#voice-list').on('change', (e) => {
let activeVP = Genshinlib.lang.voice;
@ -66,32 +74,27 @@ $(() => {
lang: {
launcher: e.target.value,
voice: Genshinlib.lang.voice
}
});
},
// This is required as the file name changes on the API but since we don't call the API before checking
// if the time is null or expired we set time to null here.
Genshinlib.updateConfig({
// This is required as the file name changes on the API but since we don't call the API before checking
// if the time is null or expired we set time to null here.
background: {
time: null,
file: Genshinlib.getConfig().background.file
file: Genshinlib.getConfig('background.file')
}
});
// Send language updates
LauncherUI.updateLang(e.target.value);
ipcRenderer.send('change-lang', { 'lang': e.target.value });
/*$('*[i18id]').each((i, element) => {
element.innerText = i18n.translate(element.getAttribute('i18id')?.toString()!);
});*/
// Send language updates
ipcRenderer.send('change-lang', { 'lang': e.target.value });
$(`#language-list option[value="${activeLang}"]`).removeProp('selected');
$(`#language-list option[value="${e.target.value}"]`).prop('selected', true);
}
});
let activeRunner = Genshinlib.getConfig().runner;
let activeRunner = Genshinlib.getConfig('runner');
Genshinlib.getRunners().then(runners => {
runners.forEach(category => {
@ -116,11 +119,11 @@ $(() => {
let div = item.find('div');
Genshinlib.downloadFile(runner.uri, path.join(Genshinlib.launcherDir, runner.name), (current: number, total: number, difference: number) => {
Tools.downloadFile(runner.uri, path.join(Genshinlib.launcherDir, runner.name), (current: number, total: number, difference: number) => {
div.text(`${ Math.round(current / total * 100) }%`);
}).then(() => {
let unpacker = runner.archive === 'tar' ?
Genshinlib.untar : Genshinlib.unzip;
Tools.untar : Tools.unzip;
unpacker(
path.join(Genshinlib.launcherDir, runner.name),
@ -165,7 +168,7 @@ $(() => {
});
});
let activeDXVK = Genshinlib.getConfig().dxvk;
let activeDXVK = Genshinlib.getConfig('dxvk');
Genshinlib.getDXVKs().then(dxvks => {
dxvks.forEach(dxvk => {
@ -187,10 +190,10 @@ $(() => {
let div = item.find('div');
Genshinlib.downloadFile(dxvk.uri, path.join(Genshinlib.launcherDir, 'dxvk-' + dxvk.version), (current: number, total: number, difference: number) => {
Tools.downloadFile(dxvk.uri, path.join(Genshinlib.launcherDir, 'dxvk-' + dxvk.version), (current: number, total: number, difference: number) => {
div.text(`${ Math.round(current / total * 100) }%`);
}).then(() => {
Genshinlib.untar(
Tools.untar(
path.join(Genshinlib.launcherDir, 'dxvk-' + dxvk.version),
Genshinlib.dxvksDir,
(current: number, total: number, difference: number) => {

View file

@ -9,6 +9,6 @@
"removeComments": true,
"outDir": "public/js"
},
"include": ["src/ts/*"],
"include": ["src/ts/*", "src/ts/lib/*"],
"exclude": ["node_modules", "**/*.spec.ts"]
}