2.2.0 (pre-release)

* This version will be released after
  all the locales will be updated
- added `HDiffPatch` class to work with HDiffPatch (https://github.com/sisong/HDiffPatch)
- added 2 new launcher states
  + game-files-changes-applying-required
  + game-outdated-files-deletion-required
- added `.hdiff` files changes applying
- updated dependencies

From previous commits:
- fixed an issue with log files' name generation
  It seems that on some specific file systems(?) `stat -c '%W' <file>`
  returns `0` as a file creation timestamp
- updated Italian
This commit is contained in:
Observer KRypt0n_ 2022-02-19 17:06:08 +02:00
parent e49115c936
commit 195220d7e0
No known key found for this signature in database
GPG key ID: 844DA47BA25FE1E2
21 changed files with 473 additions and 112 deletions

View file

@ -1,6 +1,6 @@
{ {
"applicationId": "com.gitlab.KRypt0n_.an-anime-game-launcher", "applicationId": "com.gitlab.KRypt0n_.an-anime-game-launcher",
"version": "2.1.5", "version": "2.2.0",
"defaultMode": "window", "defaultMode": "window",
"port": 0, "port": 0,
"documentRoot": "/bundle/", "documentRoot": "/bundle/",

View file

@ -1,6 +1,6 @@
{ {
"name": "an-anime-game-launcher", "name": "an-anime-game-launcher",
"version": "2.1.5", "version": "2.2.0",
"license": "GPL-3.0", "license": "GPL-3.0",
"type": "module", "type": "module",
"scripts": { "scripts": {
@ -18,17 +18,17 @@
"yaml": "^1.10.2" "yaml": "^1.10.2"
}, },
"devDependencies": { "devDependencies": {
"@neutralinojs/neu": "^9.1.2", "@neutralinojs/neu": "^9.2.0",
"@sveltejs/vite-plugin-svelte": "^1.0.0-next.37", "@sveltejs/vite-plugin-svelte": "^1.0.0-next.37",
"@tsconfig/svelte": "^3.0.0", "@tsconfig/svelte": "^3.0.0",
"@types/js-md5": "^0.4.3", "@types/js-md5": "^0.4.3",
"neutralino-appimage-bundler": "^1.3.2", "neutralino-appimage-bundler": "^1.3.2",
"sass": "^1.49.7", "sass": "^1.49.8",
"svelte": "^3.46.4", "svelte": "^3.46.4",
"svelte-check": "^2.4.3", "svelte-check": "^2.4.5",
"svelte-preprocess": "^4.10.3", "svelte-preprocess": "^4.10.3",
"tslib": "^2.3.1", "tslib": "^2.3.1",
"typescript": "^4.5.5", "typescript": "^4.5.5",
"vite": "^2.8.2" "vite": "^2.8.4"
} }
} }

48
public/hdiffpatch/LICENSE Normal file
View file

@ -0,0 +1,48 @@
MIT License
HDiffPatch
Copyright (c) 2012-2021 housisong
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
----------------------------------------------------------------------------------
libdivsufsort
Copyright (c) 2003-2008 Yuta Mori All Rights Reserved.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

BIN
public/hdiffpatch/hpatchz Executable file

Binary file not shown.

View file

@ -23,6 +23,7 @@ launcher:
game: game:
downloading: Spiel ist am herunterladen... downloading: Spiel ist am herunterladen...
unpacking: Spiel wird entpackt... unpacking: Spiel wird entpackt...
applying_changes: Änderungen werden angewandt...
deleting_outdated: Lösche veraltete dateien... deleting_outdated: Lösche veraltete dateien...
# Voice packages installation # Voice packages installation
@ -40,6 +41,14 @@ launcher:
install: Installieren install: Installieren
update: Updaten update: Updaten
apply_changes:
title: Änderungen anwenden
hint: hdiff-Änderungen an den Spieldateien anwenden
remove_outdated:
title: Alte Dateien löschen
hint: Veraltete Dateien löschen
# When the game should be patched # When the game should be patched
patching: patching:
# Patch unavailable # Patch unavailable
@ -292,6 +301,11 @@ notifications:
title: An Anime Game Launcher title: An Anime Game Launcher
body: Alle Patch-Repositories sind nicht verfügbar. Sie können das Spiel starten aber der Launcher kann sich nicht sicher sein dass es gepatcht ist. body: Alle Patch-Repositories sind nicht verfügbar. Sie können das Spiel starten aber der Launcher kann sich nicht sicher sein dass es gepatcht ist.
# HDiffPatch couldn't successfully apply game files changes
game_changes_applying_error:
title: Ein Fehler geschah, während das Spiel aktualisiert wurde
body: '{files} Dateien konnten nicht aktualisiert werden'
# ToS violation warning window # ToS violation warning window
tos_violation: tos_violation:
title: ToS-Verletzungswarnung title: ToS-Verletzungswarnung

View file

@ -23,6 +23,7 @@ launcher:
game: game:
downloading: Downloading game... downloading: Downloading game...
unpacking: Unpacking game... unpacking: Unpacking game...
applying_changes: Applying changes...
deleting_outdated: Deleting outdated files... deleting_outdated: Deleting outdated files...
# Voice packages installation # Voice packages installation
@ -40,6 +41,14 @@ launcher:
install: Install install: Install
update: Update update: Update
apply_changes:
title: Apply changes
hint: Apply hdiff changes to the game files
remove_outdated:
title: Remove outdated
hint: Remove outdated game files
# When the game should be patched # When the game should be patched
patching: patching:
# Patch unavailable # Patch unavailable
@ -291,6 +300,11 @@ notifications:
title: An Anime Game Launcher title: An Anime Game Launcher
body: None of the patch repositories are available. You'll be able to run the game, but launcher can't be sure is it patched properly body: None of the patch repositories are available. You'll be able to run the game, but launcher can't be sure is it patched properly
# HDiffPatch couldn't successfully apply game files changes
game_changes_applying_error:
title: An error occurred during game updating
body: '{files} files couldn''t be updated by the hdiff patch'
# ToS violation warning window # ToS violation warning window
tos_violation: tos_violation:
title: ToS violation warning title: ToS violation warning

View file

@ -23,6 +23,7 @@ launcher:
game: game:
downloading: Descargando el juego... downloading: Descargando el juego...
unpacking: Descomprimiendo el juego... unpacking: Descomprimiendo el juego...
applying_changes: Applying changes...
deleting_outdated: Borrando archivos viejos... deleting_outdated: Borrando archivos viejos...
# Instalación de paquetes de voz # Instalación de paquetes de voz
@ -40,6 +41,14 @@ launcher:
install: Instalar install: Instalar
update: Actualizar update: Actualizar
apply_changes:
title: Apply changes
hint: Apply hdiff changes to the game files
remove_outdated:
title: Remove outdated
hint: Remove outdated game files
# Cuando el juego debe ser parcheado # Cuando el juego debe ser parcheado
patching: patching:
# Parche no disponible # Parche no disponible
@ -290,6 +299,11 @@ notifications:
title: An Anime Game Launcher title: An Anime Game Launcher
body: Ninguno de los repositorios del parche está disponible. Podrás ejecutar el juego, pero no podemos asegurar que el parche esté aplicado correctamente body: Ninguno de los repositorios del parche está disponible. Podrás ejecutar el juego, pero no podemos asegurar que el parche esté aplicado correctamente
# HDiffPatch couldn't successfully apply game files changes
game_changes_applying_error:
title: An error occurred during game updating
body: '{files} files couldn''t be updated by the hdiff patch'
# ToS violation warning window # ToS violation warning window
tos_violation: tos_violation:
title: Advertencia de violación de ToS title: Advertencia de violación de ToS

View file

@ -23,6 +23,7 @@ launcher:
game: game:
downloading: Téléchargement du jeu... downloading: Téléchargement du jeu...
unpacking: Décompression du jeu... unpacking: Décompression du jeu...
applying_changes: Applying changes...
deleting_outdated: Suppression des fichiers non à jour... deleting_outdated: Suppression des fichiers non à jour...
# Voice packages installation # Voice packages installation
@ -40,6 +41,14 @@ launcher:
install: Installer install: Installer
update: Mise à jour update: Mise à jour
apply_changes:
title: Apply changes
hint: Apply hdiff changes to the game files
remove_outdated:
title: Remove outdated
hint: Remove outdated game files
# When the game should be patched # When the game should be patched
patching: patching:
# Patch unavailable # Patch unavailable
@ -299,6 +308,11 @@ notifications:
title: An Anime Game Launcher title: An Anime Game Launcher
body: Pas tous les dépôts des patchs sont disponibles. Vous pouvez lancer le jeu, mais le Launcher ne peut pas garantir que celui-ci est correctement patcher body: Pas tous les dépôts des patchs sont disponibles. Vous pouvez lancer le jeu, mais le Launcher ne peut pas garantir que celui-ci est correctement patcher
# HDiffPatch couldn't successfully apply game files changes
game_changes_applying_error:
title: An error occurred during game updating
body: '{files} files couldn''t be updated by the hdiff patch'
# ToS violation warning window # ToS violation warning window
tos_violation: tos_violation:
title: Violation du contrat d'utilisation title: Violation du contrat d'utilisation

View file

@ -23,6 +23,7 @@ launcher:
game: game:
downloading: Játék letöltése folyamatban... downloading: Játék letöltése folyamatban...
unpacking: Játék kibontása folyamatban... unpacking: Játék kibontása folyamatban...
applying_changes: Applying changes...
deleting_outdated: Lejárt fájlok kitörlése... deleting_outdated: Lejárt fájlok kitörlése...
# Voice packages installation # Voice packages installation
@ -40,6 +41,14 @@ launcher:
install: Telepítés install: Telepítés
update: Frissítés update: Frissítés
apply_changes:
title: Apply changes
hint: Apply hdiff changes to the game files
remove_outdated:
title: Remove outdated
hint: Remove outdated game files
# When the game should be patched # When the game should be patched
patching: patching:
# Patch unavailable # Patch unavailable
@ -291,6 +300,11 @@ notifications:
title: An Anime Game Launcher title: An Anime Game Launcher
body: A patch adattárjai nem elérhetőek. Eltudod indítani a játékot, de a launcher nem tudja meghatározni hogy patch-elve van-e body: A patch adattárjai nem elérhetőek. Eltudod indítani a játékot, de a launcher nem tudja meghatározni hogy patch-elve van-e
# HDiffPatch couldn't successfully apply game files changes
game_changes_applying_error:
title: An error occurred during game updating
body: '{files} files couldn''t be updated by the hdiff patch'
# ToS violation warning window # ToS violation warning window
tos_violation: tos_violation:
title: Felhasználói feltételek megsértése title: Felhasználói feltételek megsértése

View file

@ -23,6 +23,7 @@ launcher:
game: game:
downloading: Mengunduh game... downloading: Mengunduh game...
unpacking: Membongkar game... unpacking: Membongkar game...
applying_changes: Applying changes...
deleting_outdated: Menghapus file lama... deleting_outdated: Menghapus file lama...
# Voice packages installation # Voice packages installation
@ -40,6 +41,14 @@ launcher:
install: Pasang install: Pasang
update: Perbarui update: Perbarui
apply_changes:
title: Apply changes
hint: Apply hdiff changes to the game files
remove_outdated:
title: Remove outdated
hint: Remove outdated game files
# When the game should be patched # When the game should be patched
patching: patching:
# Patch unavailable # Patch unavailable
@ -291,6 +300,11 @@ notifications:
title: An Anime Game Launcher title: An Anime Game Launcher
body: Semua repositori patch tidak terseidia. Kamu dapat menjalankan game ini, tetapi peluncur tidak tahu secara pasti pakah patch sudah terpasang dengan benar body: Semua repositori patch tidak terseidia. Kamu dapat menjalankan game ini, tetapi peluncur tidak tahu secara pasti pakah patch sudah terpasang dengan benar
# HDiffPatch couldn't successfully apply game files changes
game_changes_applying_error:
title: An error occurred during game updating
body: '{files} files couldn''t be updated by the hdiff patch'
# ToS violation warning window # ToS violation warning window
tos_violation: tos_violation:
title: Peringatan pelanggaran Ketentuan Layanan (ToS) title: Peringatan pelanggaran Ketentuan Layanan (ToS)

View file

@ -23,6 +23,7 @@ launcher:
game: game:
downloading: Scaricando il gioco... downloading: Scaricando il gioco...
unpacking: Decomprimendo il gioco... unpacking: Decomprimendo il gioco...
applying_changes: Applying changes...
deleting_outdated: Cancellando file vecchi... deleting_outdated: Cancellando file vecchi...
# Voice packages installation # Voice packages installation
@ -40,6 +41,14 @@ launcher:
install: Installa install: Installa
update: Aggiorna update: Aggiorna
apply_changes:
title: Apply changes
hint: Apply hdiff changes to the game files
remove_outdated:
title: Remove outdated
hint: Remove outdated game files
# When the game should be patched # When the game should be patched
patching: patching:
# Patch unavailable # Patch unavailable
@ -290,6 +299,11 @@ notifications:
body: Tutte le repository della patch non sono disponibili. Puoi avviare il gioco, body: Tutte le repository della patch non sono disponibili. Puoi avviare il gioco,
ma il launcher non si può assicurare che la patch è stata applicata correttamente ma il launcher non si può assicurare che la patch è stata applicata correttamente
# HDiffPatch couldn't successfully apply game files changes
game_changes_applying_error:
title: An error occurred during game updating
body: '{files} files couldn''t be updated by the hdiff patch'
# ToS violation warning window # ToS violation warning window
tos_violation: tos_violation:
title: Avviso di violazione ToS title: Avviso di violazione ToS

View file

@ -23,6 +23,7 @@ launcher:
game: game:
downloading: Laster ned spill... downloading: Laster ned spill...
unpacking: Pakker ut spill... unpacking: Pakker ut spill...
applying_changes: Applying changes...
deleting_outdated: Fjerner utdaterte filer... deleting_outdated: Fjerner utdaterte filer...
# Voice packages installation # Voice packages installation
@ -40,6 +41,14 @@ launcher:
install: Installer install: Installer
update: Oppdater update: Oppdater
apply_changes:
title: Apply changes
hint: Apply hdiff changes to the game files
remove_outdated:
title: Remove outdated
hint: Remove outdated game files
# When the game should be patched # When the game should be patched
patching: patching:
# Patch unavailable # Patch unavailable
@ -291,6 +300,11 @@ notifications:
title: An Anime Game Launcher title: An Anime Game Launcher
body: Ingen av patch oppbevaringstedene er tilgjengelig. Det er mulig å kjøre spillet, men det er ikke mulig å forsikre seg at spillet er patchet riktig body: Ingen av patch oppbevaringstedene er tilgjengelig. Det er mulig å kjøre spillet, men det er ikke mulig å forsikre seg at spillet er patchet riktig
# HDiffPatch couldn't successfully apply game files changes
game_changes_applying_error:
title: An error occurred during game updating
body: '{files} files couldn''t be updated by the hdiff patch'
# ToS violation warning window # ToS violation warning window
tos_violation: tos_violation:
title: ToS brudd advarsel title: ToS brudd advarsel

View file

@ -23,6 +23,7 @@ launcher:
game: game:
downloading: Скачивание игры... downloading: Скачивание игры...
unpacking: Распаковка игры... unpacking: Распаковка игры...
applying_changes: Применение изменений...
deleting_outdated: Удаление устаревших файлов... deleting_outdated: Удаление устаревших файлов...
# Установка звуковых пакетов # Установка звуковых пакетов
@ -40,6 +41,14 @@ launcher:
install: Установить install: Установить
update: Обновить update: Обновить
apply_changes:
title: Применить изменения
hint: Применить hdiff изменения к файлам игры
remove_outdated:
title: Удалить устаревшее
hint: Удалить устаревшие файлы игры
# Когда игра должна быть пропатчена # Когда игра должна быть пропатчена
patching: patching:
# Патч недоступен # Патч недоступен
@ -290,6 +299,11 @@ notifications:
title: An Anime Game Launcher title: An Anime Game Launcher
body: Все репозитории патча недоступны. Вы сможете запустить игру, однако лаунчер не может знать пропатчена ли она корректно body: Все репозитории патча недоступны. Вы сможете запустить игру, однако лаунчер не может знать пропатчена ли она корректно
# HDiffPatch не смог успешно применить hdiff патчи к файлам игры
game_changes_applying_error:
title: Возникла ошибка во время обновления игры
body: '{files} файлов не смогли быть обновлены с помощью hdiff патча'
# Окно предупреждения о нарушении условий использования # Окно предупреждения о нарушении условий использования
tos_violation: tos_violation:
title: Предупреждение о нарушении правил использования title: Предупреждение о нарушении правил использования

View file

@ -23,6 +23,7 @@ launcher:
game: game:
downloading: downwoading game... -.- downloading: downwoading game... -.-
unpacking: unpacking g-game (o^▽^o) unpacking: unpacking g-game (o^▽^o)
applying_changes: appwying changes...
deleting_outdated: deweting outdated fiwes... deleting_outdated: deweting outdated fiwes...
# Voice packages installation # Voice packages installation
@ -40,6 +41,14 @@ launcher:
install: install install: install
update: u-update (/≧ ω\) update: u-update (/≧ ω\)
apply_changes:
title: appwy changes
hint: appwy hdiff changes to the game files
remove_outdated:
title: wemove outdated
hint: wemove outdated game files
# When the game should be patched # When the game should be patched
patching: patching:
# Patch unavailable # Patch unavailable
@ -290,6 +299,11 @@ notifications:
title: an anime game waunchew title: an anime game waunchew
body: a-all the patch wepositowies are not avaiwable. you'll b-be able to wun the game, but waunchew can't be sure is it patched pwopewwy body: a-all the patch wepositowies are not avaiwable. you'll b-be able to wun the game, but waunchew can't be sure is it patched pwopewwy
# HDiffPatch couldn't successfully apply game files changes
game_changes_applying_error:
title: an ewwow o-occuwwed duwing game updating
body: '{files} files couwdn''t b-be updated b-by the hdiff patch'
# ToS violation warning window # ToS violation warning window
tos_violation: tos_violation:
title: ToS violation warning title: ToS violation warning

View file

@ -39,7 +39,7 @@ const bundler = new Bundler({
output: path.join(__dirname, '../dist/An Anime Game Launcher.AppImage'), output: path.join(__dirname, '../dist/An Anime Game Launcher.AppImage'),
// Application version // Application version
version: '2.1.5' version: '2.2.0'
}); });
// Bundle project // Bundle project

23
src/ts/core/HDiffPatch.ts Normal file
View file

@ -0,0 +1,23 @@
import { Debug } from '../../empathize';
import { path } from '../../empathize';
declare const Neutralino;
export default class HDiffPatch
{
public static patch(file: string, patch: string, output: string): Promise<boolean>
{
return new Promise(async (resolve) => {
let result = await Neutralino.os.execCommand(`./public/hdiffpatch/hpatchz -f "${path.addSlashes(file)}" "${path.addSlashes(patch)}" "${path.addSlashes(output)}"`);
result = (result.stdOut ?? result.stdErr).includes('patch ok!');
Debug.log({
function: 'HDiffPatch.patch',
message: { file, patch, output, result }
});
resolve(result);
});
}
};

View file

@ -38,6 +38,8 @@ export default class State
'game-installation-available': import('./states/Install'), 'game-installation-available': import('./states/Install'),
'game-update-available': import('./states/Install'), 'game-update-available': import('./states/Install'),
'game-voice-update-required': import('./states/InstallVoice'), 'game-voice-update-required': import('./states/InstallVoice'),
'game-files-changes-applying-required': import('./states/ApplyChanges'),
'game-outdated-files-deletion-required': import('./states/RemoveOutdated'),
'test-patch-available': import('./states/ApplyPatch'), 'test-patch-available': import('./states/ApplyPatch'),
'patch-available': import('./states/ApplyPatch'), 'patch-available': import('./states/ApplyPatch'),
@ -254,6 +256,20 @@ export default class State
break; break;
case 'game-files-changes-applying-required':
this.launchButton.textContent = dictionary['installation']['apply_changes']['title'];
this.launchButton.setAttribute('aria-label', dictionary['installation']['apply_changes']['hint']);
break;
case 'game-outdated-files-deletion-required':
this.launchButton.textContent = dictionary['installation']['remove_outdated']['title'];
this.launchButton.setAttribute('aria-label', dictionary['installation']['remove_outdated']['hint']);
break;
case 'patch-available': case 'patch-available':
this.launchButton.textContent = dictionary['patching']['stable']; this.launchButton.textContent = dictionary['patching']['stable'];
@ -385,65 +401,76 @@ export default class State
else else
{ {
const installedVoices = await Voice.installed; const gameDir = await constants.paths.gameDir;
const selectedVoices = await Voice.selected;
let voiceUpdateRequired = installedVoices.length != selectedVoices.length || installedVoices.length === 0; if (await fs.exists(`${gameDir}/hdifffiles.txt`))
state = 'game-files-changes-applying-required';
if (!voiceUpdateRequired) else if (await fs.exists(`${gameDir}/deletefiles.txt`))
{ state = 'game-outdated-files-deletion-required';
for (const installedVoice of installedVoices)
if (installedVoice.version != gameCurrent || !selectedVoices.includes(installedVoice.lang))
{
voiceUpdateRequired = true;
break;
}
}
// TODO: download default voice language if user removed all of them
if (voiceUpdateRequired)
state = 'game-voice-update-required';
else else
{ {
try const installedVoices = await Voice.installed;
const selectedVoices = await Voice.selected;
let voiceUpdateRequired = installedVoices.length != selectedVoices.length || installedVoices.length === 0;
if (!voiceUpdateRequired)
{ {
const patch = await Patch.latest; for (const installedVoice of installedVoices)
if (installedVoice.version != gameCurrent || !selectedVoices.includes(installedVoice.lang))
{
voiceUpdateRequired = true;
// If the latest game version is, for example, 2.3.0 break;
// and the patch is 2.4.0 preparation, it means that }
// 2.4.0 will be released soon, but since it's still not released
// we shouldn't show something about it to user and just let him play the game
if (gameLatest.game.latest.version === patch.version && !patch.applied)
{
state = patch.state == 'preparation' ?
'patch-unavailable' : (patch.state == 'testing' ?
'test-patch-available' : 'patch-available');
}
// Patch is more important than game pre-downloading
// because otherwise we will not be able to play the game
else if (gameLatest.pre_download_game && !await Game.isUpdatePredownloaded())
state = 'game-pre-installation-available';
else if (gameLatest.pre_download_game && !await Voice.isUpdatePredownloaded(await Voice.selected))
state = 'game-voice-pre-installation-available';
else state = 'game-launch-available';
} }
// Patch.latest can throw an error if all of patch's servers // TODO: download default voice language if user removed all of them
// are not available, and we must notify user about that if (voiceUpdateRequired)
catch state = 'game-voice-update-required';
{
state = 'game-launch-available';
Notification.show({ else
...(Locales.translate('notifications.patch_repos_unavailable') as { title: string, body: string }), {
icon: `${constants.paths.appDir}/public/images/baal64-transparent.png`, try
importance: 'critical' {
}); const patch = await Patch.latest;
// If the latest game version is, for example, 2.3.0
// and the patch is 2.4.0 preparation, it means that
// 2.4.0 will be released soon, but since it's still not released
// we shouldn't show something about it to user and just let him play the game
if (gameLatest.game.latest.version === patch.version && !patch.applied)
{
state = patch.state == 'preparation' ?
'patch-unavailable' : (patch.state == 'testing' ?
'test-patch-available' : 'patch-available');
}
// Patch is more important than game pre-downloading
// because otherwise we will not be able to play the game
else if (gameLatest.pre_download_game && !await Game.isUpdatePredownloaded())
state = 'game-pre-installation-available';
else if (gameLatest.pre_download_game && !await Voice.isUpdatePredownloaded(await Voice.selected))
state = 'game-voice-pre-installation-available';
else state = 'game-launch-available';
}
// Patch.latest can throw an error if all of patch's servers
// are not available, and we must notify user about that
catch
{
state = 'game-launch-available';
Notification.show({
...(Locales.translate('notifications.patch_repos_unavailable') as { title: string, body: string }),
icon: `${constants.paths.appDir}/public/images/baal64-transparent.png`,
importance: 'critical'
});
}
} }
} }
} }

View file

@ -0,0 +1,95 @@
import type Launcher from '../../Launcher';
import { Debug, Notification, fs } from '../../../empathize';
import constants from '../../Constants';
import Locales from '../Locales';
import HDiffPatch from '../../core/HDiffPatch';
declare const Neutralino;
export default (launcher: Launcher): Promise<void> => {
return new Promise(async (resolve) => {
const gameDir = await constants.paths.gameDir;
Neutralino.filesystem.readFile(`${gameDir}/hdifffiles.txt`)
.then(async (files) => {
let patchErrors = 0;
files = files.split(/\r\n|\r|\n/).filter((file) => file != '');
if (files.length > 0)
{
launcher.progressBar?.init({
label: Locales.translate('launcher.progress.game.applying_changes') as string,
showSpeed: false,
showEta: true,
showPercents: true,
showTotals: false
});
launcher.progressBar?.show();
let current = 0, total = files.length;
for (const file of files)
{
// {"remoteName": "AnAnimeGame_Data/StreamingAssets/Audio/GeneratedSoundBanks/Windows/Banks0.pck"}
const filePatchInfo = JSON.parse(file) as { remoteName: string };
if (await fs.exists(`${gameDir}/${filePatchInfo.remoteName}.hdiff`))
{
const patchResult = await HDiffPatch.patch(
`${gameDir}/${filePatchInfo.remoteName}`,
`${gameDir}/${filePatchInfo.remoteName}.hdiff`,
`${gameDir}/${filePatchInfo.remoteName}.hdiff_patched`
);
if (patchResult)
{
await Neutralino.filesystem.removeFile(`${gameDir}/${filePatchInfo.remoteName}`);
await Neutralino.filesystem.removeFile(`${gameDir}/${filePatchInfo.remoteName}.hdiff`);
await Neutralino.filesystem.moveFile(
`${gameDir}/${filePatchInfo.remoteName}.hdiff_patched`,
`${gameDir}/${filePatchInfo.remoteName}`
);
}
else ++patchErrors;
}
launcher.progressBar?.update(++current, total, 1);
}
if (patchErrors > 0)
{
const locale = Locales.translate('notifications.game_changes_applying_error') as { title: string, body: string };
Notification.show({
title: locale.title,
body: locale.body.replace('{files}', patchErrors.toString()),
icon: `${constants.paths.appDir}/public/images/baal64-transparent.png`,
importance: 'critical'
});
}
Debug.log({
function: 'Launcher/States/Install',
message: [
`Applied changes${patchErrors > 0 ? ` (${patchErrors} errors)` : ''}:`,
...files
]
});
}
if (patchErrors === 0)
await Neutralino.filesystem.removeFile(`${gameDir}/hdifffiles.txt`);
launcher.progressBar?.hide();
resolve();
})
.catch(() => resolve());
});
};

View file

@ -1,15 +1,10 @@
import { get as svelteget } from 'svelte/store';
import { _ } from 'svelte-i18n';
import type Launcher from '../../Launcher'; import type Launcher from '../../Launcher';
import { Debug } from '../../../empathize';
import Game from '../../Game'; import Game from '../../Game';
import Prefix from '../../core/Prefix'; import Prefix from '../../core/Prefix';
import constants from '../../Constants'; import constants from '../../Constants';
import Locales from '../Locales';
declare const Neutralino; import { promisify } from '@empathize/framework';
export default (launcher: Launcher): Promise<void> => { export default (launcher: Launcher): Promise<void> => {
return new Promise(async (resolve) => { return new Promise(async (resolve) => {
@ -31,7 +26,7 @@ export default (launcher: Launcher): Promise<void> => {
Game.update(prevGameVersion).then((stream) => { Game.update(prevGameVersion).then((stream) => {
launcher.progressBar?.init({ launcher.progressBar?.init({
label: svelteget(_)('launcher.progress.game.downloading'), label: Locales.translate('launcher.progress.game.downloading') as string,
showSpeed: true, showSpeed: true,
showEta: true, showEta: true,
showPercents: true, showPercents: true,
@ -48,14 +43,14 @@ export default (launcher: Launcher): Promise<void> => {
{ {
stream?.pauseDownload(); stream?.pauseDownload();
launcher.state!.pauseButton.textContent = svelteget(_)('launcher.progress.resume'); launcher.state!.pauseButton.textContent = Locales.translate('launcher.progress.resume') as string;
} }
else else
{ {
stream?.resumeDownload(); stream?.resumeDownload();
launcher.state!.pauseButton.textContent = svelteget(_)('launcher.progress.pause'); launcher.state!.pauseButton.textContent = Locales.translate('launcher.progress.pause') as string;
} }
paused = !paused; paused = !paused;
@ -69,7 +64,7 @@ export default (launcher: Launcher): Promise<void> => {
stream?.unpackStart(() => { stream?.unpackStart(() => {
launcher.progressBar?.init({ launcher.progressBar?.init({
label: svelteget(_)('launcher.progress.game.unpacking'), label: Locales.translate('launcher.progress.game.unpacking') as string,
showSpeed: true, showSpeed: true,
showEta: true, showEta: true,
showPercents: true, showPercents: true,
@ -87,56 +82,31 @@ export default (launcher: Launcher): Promise<void> => {
}); });
stream?.unpackFinish(async () => { stream?.unpackFinish(async () => {
const gameDir = await constants.paths.gameDir; // Hide pause/resume button
launcher.state!.pauseButton.style['display'] = 'none';
// Deleting outdated files await promisify({
Neutralino.filesystem.readFile(`${gameDir}/deletefiles.txt`) callbacks: [
.then(async (files) => { // Applying game's files changes
files = files.split(/\r\n|\r|\n/).filter((file) => file != ''); (): Promise<void> => new Promise((resolve) => {
import('./ApplyChanges').then((module) => {
if (files.length > 0) module.default(launcher).then(() => resolve());
{
launcher.progressBar?.init({
label: svelteget(_)('launcher.progress.game.deleting_outdated'),
showSpeed: false,
showEta: true,
showPercents: true,
showTotals: false
}); });
}),
let current = 0, total = files.length; // Deleting outdated files
(): Promise<void> => new Promise((resolve) => {
for (const file of files) import('./RemoveOutdated').then((module) => {
{ module.default(launcher).then(() => resolve());
await Neutralino.filesystem.removeFile(`${gameDir}/${file}`);
launcher.progressBar?.update(++current, total, 1);
}
Debug.log({
function: 'Launcher/States/Install',
message: [
'Deleted outdated files:',
...files
]
}); });
} })
]
await Neutralino.filesystem.removeFile(`${gameDir}/deletefiles.txt`); });
installVoice();
})
.catch(() => installVoice());
// Download voice package when the game itself has been installed // Download voice package when the game itself has been installed
const installVoice = () => { import('./InstallVoice').then((module) => {
// Hide pause/resume button module.default(launcher).then(() => resolve());
launcher.state!.pauseButton.style['display'] = 'none'; });
import('./InstallVoice').then((module) => {
module.default(launcher).then(() => resolve());
});
};
}); });
}); });
}; };

View file

@ -0,0 +1,56 @@
import type Launcher from '../../Launcher';
import { Debug } from '../../../empathize';
import constants from '../../Constants';
import Locales from '../Locales';
declare const Neutralino;
export default (launcher: Launcher): Promise<void> => {
return new Promise(async (resolve) => {
const gameDir = await constants.paths.gameDir;
Neutralino.filesystem.readFile(`${gameDir}/deletefiles.txt`)
.then(async (files) => {
files = files.split(/\r\n|\r|\n/).filter((file) => file != '');
if (files.length > 0)
{
launcher.progressBar?.init({
label: Locales.translate('launcher.progress.game.deleting_outdated') as string,
showSpeed: false,
showEta: true,
showPercents: true,
showTotals: false
});
launcher.progressBar?.show();
let current = 0, total = files.length;
for (const file of files)
{
await Neutralino.filesystem.removeFile(`${gameDir}/${file}`);
launcher.progressBar?.update(++current, total, 1);
}
Debug.log({
function: 'Launcher/States/RemoveOutdated',
message: [
'Deleted outdated files:',
...files
]
});
}
await Neutralino.filesystem.removeFile(`${gameDir}/deletefiles.txt`);
launcher.progressBar?.hide();
resolve();
})
.catch(() => resolve());
});
};

View file

@ -21,6 +21,8 @@ type LauncherState =
| 'game-installation-available' | 'game-installation-available'
| 'game-update-available' | 'game-update-available'
| 'game-voice-update-required' | 'game-voice-update-required'
| 'game-files-changes-applying-required'
| 'game-outdated-files-deletion-required'
| 'game-pre-installation-available' | 'game-pre-installation-available'
| 'game-voice-pre-installation-available' | 'game-voice-pre-installation-available'
| 'game-launch-available'; | 'game-launch-available';