mirror of
https://github.com/an-anime-team/an-anime-game-launcher.git
synced 2025-02-27 04:40:44 +03:00
API improvements
- fixed `Game.getLatestData()` method - added `Patch.install()` method - added downloaded archive auto-deletion in `AbstractInstaller` - highly improved `promisify()` function - added `source` field for the patch info
This commit is contained in:
parent
bd41bd1f46
commit
843196e0e1
8 changed files with 215 additions and 15 deletions
|
@ -130,12 +130,13 @@ This is our current roadmap goals. You can find older ones [here](ROADMAP.md)
|
|||
* <s>Ability to parse current installed voice packs and get selected one</s>
|
||||
* <s>Ability to get latest available voice packs</s>
|
||||
* <s>Ability to download and install updates</s>
|
||||
* Make `Patch` class to control patch-related features
|
||||
* <s>Make `Patch` class to control patch-related features</s>
|
||||
* <s>Ability to get current installed patch</s>
|
||||
* <s>Ability to get latest available patch</s>
|
||||
* Ability to download and install it
|
||||
* <s>Ability to download and install it</s>
|
||||
* Add project binaries bundling
|
||||
* AppImage
|
||||
* <s>AppImage</s> *(seems to be impossible)*
|
||||
* One-time small installation script because then launcher will have auto updates
|
||||
|
||||
#### Launcher functions
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@ import Launcher from '../ts/Launcher';
|
|||
import Configs from '../ts/Configs';
|
||||
import constants from '../ts/Constants';
|
||||
import promisify from '../ts/core/promisify';
|
||||
import Process from '../ts/neutralino/Process';
|
||||
|
||||
promisify(async () => {
|
||||
Configs.defaults({
|
||||
|
|
|
@ -183,6 +183,9 @@ export default class constants
|
|||
public static readonly versionsUri: string = `${this.uri.api}/resource?key=gcStgarh&launcher_id=10`;
|
||||
public static readonly backgroundUri: string = `${this.uri.api}/content?filter_adv=true&launcher_id=10&key=gcStgarh&language=`;
|
||||
|
||||
/**
|
||||
* Get a URI to the specified patch repository archive
|
||||
*/
|
||||
public static getPatchUri(source: 'origin' | 'additional'): string
|
||||
{
|
||||
return `${this.uri.patch[source]}/archive/master.zip`;
|
||||
|
|
|
@ -58,7 +58,7 @@ export default class Game
|
|||
|
||||
if (response.ok)
|
||||
{
|
||||
const json: ServerResponse = await (response as any).json();
|
||||
const json: ServerResponse = JSON.parse(await response.body());
|
||||
|
||||
if (json.message == 'OK')
|
||||
resolve(json.data);
|
||||
|
|
140
src/ts/Patch.ts
140
src/ts/Patch.ts
|
@ -1,13 +1,125 @@
|
|||
import type {
|
||||
PatchState,
|
||||
PatchInfo
|
||||
} from './types/Patch';
|
||||
import type { PatchInfo } from './types/Patch';
|
||||
|
||||
import md5 from 'js-md5';
|
||||
|
||||
import constants from './Constants';
|
||||
import Game from './Game';
|
||||
import fetch from './core/Fetch';
|
||||
import AbstractInstaller from './core/AbstractInstaller';
|
||||
import promisify from './core/promisify';
|
||||
import Process from './neutralino/Process';
|
||||
|
||||
declare const Neutralino;
|
||||
|
||||
class Stream extends AbstractInstaller
|
||||
{
|
||||
protected userUnpackFinishCallback?: () => void;
|
||||
protected onPatchFinish?: () => void;
|
||||
|
||||
protected patchFinished: boolean = false;
|
||||
|
||||
public constructor(uri: string, version: string|null = null)
|
||||
{
|
||||
super(uri, constants.paths.launcherDir);
|
||||
|
||||
/**
|
||||
* We'll make our own AbstractInstaller unpacking finish event
|
||||
* and provide some hack to call another user-provided function
|
||||
* if he wants to make something after patch's archive unpacking
|
||||
*/
|
||||
this.onUnpackFinish = async () => {
|
||||
if (this.userUnpackFinishCallback)
|
||||
this.userUnpackFinishCallback();
|
||||
|
||||
// Find patch version if it wasn't provided
|
||||
if (version === null)
|
||||
version = (await Patch.latest).version;
|
||||
|
||||
const patchDir = `${await constants.paths.launcherDir}/dawn/${version.replaceAll('.', '')}`;
|
||||
|
||||
/**
|
||||
* Patch out the testing phase content from the shell files
|
||||
* if active and make sure the shell files are executable
|
||||
*/
|
||||
const pipeline = promisify({
|
||||
callbacks: [
|
||||
/**
|
||||
* Remove test version restrictions from the main patch
|
||||
*/
|
||||
() => Neutralino.os.execCommand(`cd '${patchDir}' && sed -i '/^echo "If you would like to test this patch, modify this script and remove the line below this one."/,+5d' patch.sh`),
|
||||
|
||||
/**
|
||||
* Remove test version restrictions from the anti-login crash patch
|
||||
*/
|
||||
() => Neutralino.os.execCommand(`cd '${patchDir}' && sed -i '/^echo " necessary afterwards (Friday?). If that's the case, comment the line below."/,+2d' patch_anti_logincrash.sh`),
|
||||
|
||||
/**
|
||||
* Make the main patch executable
|
||||
*/
|
||||
() => Neutralino.os.execCommand(`chmod +x '${patchDir}/patch.sh'`),
|
||||
|
||||
/**
|
||||
* Make the anti-login crash patch executable
|
||||
*/
|
||||
() => Neutralino.os.execCommand(`chmod +x '${patchDir}/patch_anti_logincrash.sh'`),
|
||||
|
||||
/**
|
||||
* Execute the main patch installation script
|
||||
*/
|
||||
(): Promise<void> => {
|
||||
return new Promise(async (resolve) => {
|
||||
Process.run(`yes yes | bash '${patchDir}/patch.sh'`, {
|
||||
cwd: await constants.paths.gameDir
|
||||
}).then((process) => {
|
||||
process.finish(() => resolve());
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Execute the anti-login crash patch installation script
|
||||
*/
|
||||
(): Promise<void> => {
|
||||
return new Promise(async (resolve) => {
|
||||
Process.run(`yes | bash '${patchDir}/patch_anti_logincrash.sh'`, {
|
||||
cwd: await constants.paths.gameDir
|
||||
}).then((process) => {
|
||||
process.finish(() => resolve());
|
||||
});
|
||||
});
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
// When all the things above was done
|
||||
pipeline.then(() => {
|
||||
this.patchFinished = true;
|
||||
|
||||
if (this.onPatchFinish)
|
||||
this.onPatchFinish();
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
public unpackFinish(callback: () => void)
|
||||
{
|
||||
this.userUnpackFinishCallback = callback;
|
||||
|
||||
if (this.unpackFinished)
|
||||
callback();
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify event that will be called when the patch will be applied
|
||||
*/
|
||||
public patchFinish(callback: () => void)
|
||||
{
|
||||
this.onPatchFinish = callback;
|
||||
|
||||
if (this.patchFinished)
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
||||
export default class Patch
|
||||
{
|
||||
|
@ -95,7 +207,8 @@ export default class Patch
|
|||
resolve({
|
||||
version: version,
|
||||
state: 'preparation',
|
||||
applied: false
|
||||
applied: false,
|
||||
source: source
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -118,7 +231,8 @@ export default class Patch
|
|||
let patchInfo: PatchInfo = {
|
||||
version: version,
|
||||
state: response.includes(stableMark) ? 'stable' : 'testing',
|
||||
applied: false
|
||||
applied: false,
|
||||
source: source
|
||||
};
|
||||
|
||||
const originalPlayer = /if \[ "\${sum}" != "([a-z0-9]{32})" \]; then/mg.exec(response);
|
||||
|
@ -138,4 +252,18 @@ export default class Patch
|
|||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get patch installation stream
|
||||
*/
|
||||
public static install(): Promise<Stream>
|
||||
{
|
||||
return new Promise((resolve, reject) => {
|
||||
this.latest
|
||||
.then((patch) => resolve(new Stream(constants.getPatchUri(patch.source ?? 'origin'), patch.version)))
|
||||
.catch((err) => reject(err));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export { Stream };
|
||||
|
|
|
@ -2,6 +2,8 @@ import constants from '../Constants';
|
|||
import Downloader from './Downloader';
|
||||
import Archive from './Archive';
|
||||
|
||||
declare const Neutralino;
|
||||
|
||||
export default abstract class Installer
|
||||
{
|
||||
/**
|
||||
|
@ -75,6 +77,8 @@ export default abstract class Installer
|
|||
|
||||
stream.finish(() => {
|
||||
this.unpackFinished = true;
|
||||
|
||||
Neutralino.filesystem.removeFile(archivePath);
|
||||
|
||||
if (this.onUnpackFinish)
|
||||
this.onUnpackFinish();
|
||||
|
|
|
@ -1,9 +1,69 @@
|
|||
type callback = () => any;
|
||||
|
||||
type PromiseOptions = {
|
||||
callbacks: callback[];
|
||||
|
||||
/**
|
||||
* If true, then all the callbacks will be called
|
||||
* at the same time and promisify will be resolved
|
||||
* when all of them will be finished
|
||||
*
|
||||
* Otherwise, callbacks will be called one after the other
|
||||
* and promisify will be resolved with the last one
|
||||
*/
|
||||
callAtOnce?: boolean;
|
||||
|
||||
/**
|
||||
* [callAtOnce: true] updates interval in ms
|
||||
*
|
||||
* @default 100
|
||||
*/
|
||||
interval?: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* Make a promise from a synchronous function and run it
|
||||
* Make a promise from a function(s) and run it
|
||||
*/
|
||||
export default function promisify(callback: () => any): Promise<any>
|
||||
export default function promisify(callback: callback|PromiseOptions): Promise<any>
|
||||
{
|
||||
return new Promise((resolve) => {
|
||||
resolve(callback());
|
||||
return new Promise(async (resolve) => {
|
||||
if (typeof callback === 'function')
|
||||
resolve(await Promise.resolve(callback()));
|
||||
|
||||
else
|
||||
{
|
||||
let outputs = {};
|
||||
|
||||
if (callback.callAtOnce)
|
||||
{
|
||||
let remained = callback.callbacks.length;
|
||||
|
||||
for (let i = 0; i < callback.callbacks.length; ++i)
|
||||
promisify(callback.callbacks[i]).then((output) => {
|
||||
outputs[i] = output;
|
||||
|
||||
--remained;
|
||||
});
|
||||
|
||||
const updater = () => {
|
||||
if (remained > 0)
|
||||
setTimeout(updater, callback.interval ?? 100);
|
||||
|
||||
else resolve(outputs);
|
||||
};
|
||||
|
||||
setTimeout(updater, callback.interval ?? 100);
|
||||
}
|
||||
|
||||
else for (let i = 0; i < callback.callbacks.length; ++i)
|
||||
outputs[i] = await promisify(callback.callbacks[i]());
|
||||
|
||||
resolve(outputs);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export type {
|
||||
PromiseOptions,
|
||||
callback
|
||||
};
|
||||
|
|
5
src/ts/types/Patch.d.ts
vendored
5
src/ts/types/Patch.d.ts
vendored
|
@ -14,6 +14,11 @@ type PatchInfo = {
|
|||
* If the patch was applied
|
||||
*/
|
||||
applied: boolean;
|
||||
|
||||
/**
|
||||
* Source where this info was got from
|
||||
*/
|
||||
source?: 'origin' | 'additional';
|
||||
};
|
||||
|
||||
export type {
|
||||
|
|
Loading…
Add table
Reference in a new issue