Added telemetry checking

- updated vite version
- made `Game.isTelemetryDisabled()` method to check whether game's telemetry is disabled
- made `Domain` class and `Domain.getInfo()` method
  to get information about some domain
- made `Notifications` class to manage system notifications
- added telemetry checking before game launching
This commit is contained in:
Observer KRypt0n_ 2021-12-28 13:27:29 +02:00
parent 10b910c2ae
commit 0c1a9e68ca
No known key found for this signature in database
GPG key ID: DC5D4EC1303465DA
10 changed files with 254 additions and 104 deletions

View file

@ -55,25 +55,26 @@ To work this launcher requires
| curl | To download archives with game, voice data, runners and so on |
| xdelta3 | To apply the patch to the game |
| cabextract | To install fonts to the wine prefix |
| notify-send | To send system notifications |
## Install
### apt-get
```sh
sudo apt-get install webkit2gtk unzip tar git curl xdelta3 cabextract
sudo apt-get install webkit2gtk unzip tar git curl xdelta3 cabextract notify-send
```
### pacman
```sh
sudo pacman -Syu webkit2gtk unzip tar git curl xdelta3 cabextract
sudo pacman -Syu webkit2gtk unzip tar git curl xdelta3 cabextract notify-send
```
### dnf
```sh
sudo dnf install webkit2gtk unzip tar git curl xdelta cabextract
sudo dnf install webkit2gtk unzip tar git curl xdelta cabextract notify-send
```
# Additional requirements
@ -162,8 +163,8 @@ This is our current roadmap goals. You can find older ones [here](ROADMAP.md)
* PropertiesEditor
* Rewrite sass code, provide more flexible theming ability
* <s>Add `svelte-i18n`</s>
* <s>Telemetry checking</s>
* Game pre-installation
* Telemetry checking
* Launcher auto-updates
* Statistics window
* Debugger

View file

@ -25,6 +25,6 @@
"svelte-preprocess": "^4.10.1",
"tslib": "^2.3.1",
"typescript": "^4.5.4",
"vite": "^2.7.7"
"vite": "^2.7.8"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View file

@ -1,7 +1,7 @@
import Configs from './Configs';
declare const Neutralino;
declare const NL_PATH;
declare const NL_CWD;
class Prefix
{
@ -41,7 +41,7 @@ class Paths
/**
* Directory where the launcher's executable stored
*/
public static readonly appDir: string = NL_PATH;
public static readonly appDir: string = NL_CWD;
/**
* Shaders directory

View file

@ -8,6 +8,8 @@ import type {
import constants from './Constants';
import fetch from './core/Fetch';
import AbstractInstaller from './core/AbstractInstaller';
import Domain from './core/Domain';
import promisify from './core/promisify';
declare const Neutralino;
@ -144,6 +146,32 @@ export default class Game
.catch((error) => reject(error));
});
}
/**
* Check if the telemetry servers are disabled
*/
public static isTelemetryDisabled(): Promise<boolean>
{
return new Promise(async (resolve) => {
const pipeline = promisify({
callbacks: await constants.uri.telemetry.map((domain) => {
return new Promise((resolve) => {
Domain.getInfo(domain).then((info) => resolve(info.available));
});
}),
callAtOnce: true,
interval: 500
});
pipeline.then((result) => {
let disabled = false;
Object.values(result).forEach((value) => disabled ||= value as boolean);
resolve(disabled === false);
});
});
}
}
export { Stream };

36
src/ts/core/Domain.ts Normal file
View file

@ -0,0 +1,36 @@
import type { DomainInfo } from '../types/Domain';
import Process from '../neutralino/Process';
export default class Domain
{
public static getInfo(uri: string): Promise<DomainInfo>
{
return new Promise(async (resolve) => {
const process = await Process.run(`ping -n 1 -w 1 -B ${uri}`);
// If something will be wrong - at least we'll have
// to wait 1.5 seconds instread of 2
process.runningInterval = 500;
process.outputInterval = 500;
let output = '';
process.output((outputPart) => {
output += outputPart;
const regex = /PING (.*) \(([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})\) from ([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}) : [\d]+\([\d]+\) bytes of data/gm.exec(output);
if (regex !== null)
{
resolve({
uri: regex[1],
remoteIp: regex[2],
localIp: regex[3],
available: regex[2] !== regex[3]
});
}
});
});
}
};

View file

@ -0,0 +1,32 @@
import type { NotificationsOptions } from '../types/Notifications';
import Process from '../neutralino/Process';
declare const Neutralino;
export default class Notifications
{
/**
* Show notification
*/
public static show(options: NotificationsOptions)
{
let command = `notify-send '${Process.addSlashes(options.title)}' '${Process.addSlashes(options.body)}'`;
// Specify notification icon
if (options.icon)
command += ` -i '${Process.addSlashes(options.icon)}'`;
// Specify notification duration
if (options.duration)
command += ` -d ${options.duration}`;
// Specify notification importance
if (options.importance)
command += ` -u ${options.importance}`;
Neutralino.os.execCommand(command, {
background: true
});
}
};

View file

@ -1,124 +1,145 @@
import Configs from '../../Configs';
import constants from '../../Constants';
import Notifications from '../../core/Notifications';
import Runners from '../../core/Runners';
import Game from '../../Game';
import Process from '../../neutralino/Process';
declare const Neutralino;
export default (): Promise<void> => {
return new Promise(async (resolve) => {
/**
* Selecting wine executable
*/
let wineExeutable = 'wine';
const telemetry = await Game.isTelemetryDisabled();
const runner = await Runners.current();
if (runner !== null)
// If telemetry servers are not disabled
if (telemetry)
{
wineExeutable = `${await constants.paths.runnersDir}/${runner.name}/${runner.files.wine}`;
const icon = `${constants.paths.appDir}/public/icons/baal64-transparent.png`;
try
Notifications.show({
title: 'An Anime Game Launcher',
body: 'Telemetry servers are not disabled',
icon: icon,
importance: 'critical'
});
}
// Otherwise run the game
else
{
/**
* Selecting wine executable
*/
let wineExeutable = 'wine';
const runner = await Runners.current();
if (runner !== null)
{
Neutralino.filesystem.getStats(wineExeutable);
wineExeutable = `${await constants.paths.runnersDir}/${runner.name}/${runner.files.wine}`;
try
{
Neutralino.filesystem.getStats(wineExeutable);
}
catch
{
wineExeutable = 'wine';
await Configs.set('runner', null);
}
}
catch
{
wineExeutable = 'wine';
console.log(`Wine executable: ${wineExeutable}`);
await Configs.set('runner', null);
// Some special variables
let env: any = {};
/**
* HUD
*/
switch (await Configs.get('hud'))
{
case 'dxvk':
env['DXVK_HUD'] = 'fps,frametimes';
break;
case 'mangohud':
env['MANGOHUD'] = 1;
break;
}
}
console.log(`Wine executable: ${wineExeutable}`);
/**
* Shaders
*/
const shaders = await Configs.get('shaders');
// Some special variables
let env: any = {};
/**
* HUD
*/
switch (await Configs.get('hud'))
{
case 'dxvk':
env['DXVK_HUD'] = 'fps,frametimes';
break;
case 'mangohud':
env['MANGOHUD'] = 1;
break;
}
/**
* Shaders
*/
const shaders = await Configs.get('shaders');
if (shaders !== null)
{
const userShadersFile = `${constants.paths.shadersDir}/${shaders}/vkBasalt.conf`;
const launcherShadersFile = `${await constants.paths.launcherDir}/vkBasalt.conf`;
env['ENABLE_VKBASALT'] = 1;
env['VKBASALT_CONFIG_FILE'] = launcherShadersFile;
await Neutralino.filesystem.writeFile(launcherShadersFile, await Neutralino.filesystem.readFile(userShadersFile));
}
/**
* GPU selection
*/
/*if (LauncherLib.getConfig('gpu') != 'default')
{
const gpu = await SwitcherooControl.getGpuByName(LauncherLib.getConfig('gpu'));
if (gpu)
if (shaders !== null)
{
env = {
const userShadersFile = `${constants.paths.shadersDir}/${shaders}/vkBasalt.conf`;
const launcherShadersFile = `${await constants.paths.launcherDir}/vkBasalt.conf`;
env['ENABLE_VKBASALT'] = 1;
env['VKBASALT_CONFIG_FILE'] = launcherShadersFile;
await Neutralino.filesystem.writeFile(launcherShadersFile, await Neutralino.filesystem.readFile(userShadersFile));
}
/**
* GPU selection
*/
/*if (LauncherLib.getConfig('gpu') != 'default')
{
const gpu = await SwitcherooControl.getGpuByName(LauncherLib.getConfig('gpu'));
if (gpu)
{
env = {
...env,
...SwitcherooControl.getEnvAsObject(gpu)
};
}
else console.warn(`GPU ${LauncherLib.getConfig('gpu')} not found. Launching on the default GPU`);
}*/
// let command = `${wineExeutable} ${LauncherLib.getConfig('fpsunlock') ? 'fpsunlock.bat' : 'launcher.bat'}`;
/**
* Gamemode integration
*/
/*if (LauncherLib.getConfig('gamemode'))
command = `gamemoderun ${command}`;*/
const command = `${wineExeutable} launcher.bat`;
console.log(`Execution command: ${command}`);
/**
* Starting the game
*/
const startTime = Date.now();
const process = await Process.run(command, {
env: {
...env,
...SwitcherooControl.getEnvAsObject(gpu)
};
}
else console.warn(`GPU ${LauncherLib.getConfig('gpu')} not found. Launching on the default GPU`);
}*/
// let command = `${wineExeutable} ${LauncherLib.getConfig('fpsunlock') ? 'fpsunlock.bat' : 'launcher.bat'}`;
WINEPREFIX: await constants.paths.prefix.current
},
cwd: await constants.paths.gameDir
});
/**
* Gamemode integration
*/
/*if (LauncherLib.getConfig('gamemode'))
command = `gamemoderun ${command}`;*/
// Game closed event
process.finish(() => {
const stopTime = Date.now();
const command = `${wineExeutable} launcher.bat`;
// todo
console.log(`Execution command: ${command}`);
/**
* Starting the game
*/
const startTime = Date.now();
const process = await Process.run(command, {
env: {
...env,
WINEPREFIX: await constants.paths.prefix.current
},
cwd: await constants.paths.gameDir
});
// Game closed event
process.finish(() => {
const stopTime = Date.now();
// todo
resolve();
});
resolve();
});
}
});
};

8
src/ts/types/Domain.d.ts vendored Normal file
View file

@ -0,0 +1,8 @@
type DomainInfo = {
uri: string;
remoteIp: string;
localIp: string;
available: boolean;
};
export type { DomainInfo };

24
src/ts/types/Notifications.d.ts vendored Normal file
View file

@ -0,0 +1,24 @@
type NotificationsOptions = {
title: string;
body: string;
/**
* Icon name or path
*/
icon?: string;
/**
* Number of seconds this notification
* will be visible
*/
duration?: number;
/**
* Importance of the notification
*
* @default "normal"
*/
importance?: 'low' | 'normal' | 'critical';
};
export type { NotificationsOptions };