intial commit files

This commit is contained in:
Ben
2023-10-02 19:52:53 -05:00
parent b58e0e3161
commit d5bc8ad13a
9 changed files with 446 additions and 414 deletions

View File

@@ -1,9 +0,0 @@
import '@testing-library/jest-dom';
import { render } from '@testing-library/react';
import App from '../renderer/App';
describe('App', () => {
it('should render', () => {
expect(render(<App />)).toBeTruthy();
});
});

View File

@@ -1,15 +0,0 @@
const Channels = {
WOW_LAUNCH: 'launch-wow',
WOW_LAUNCH_ERROR: 'launch-wow-error',
WOW_CLIENT_EXIT: 'launch-wow-exit',
APP_INFO: 'app-info',
} as const;
const PLATFORM = {
WINDOWS: 'win32',
MAC: 'darwin',
LINUX: 'linux',
} as const
export default Channels;
export { PLATFORM };

10
src/main/libs/index.ts Normal file
View File

@@ -0,0 +1,10 @@
import * as FileManager from './FileManager';
import * as Downloader from './Downloader';
import * as Emitter from './Emitter';
export {
FileManager,
Downloader,
Emitter
};

6
src/main/libs/utils.ts Normal file
View File

@@ -0,0 +1,6 @@
/* eslint-disable import/prefer-default-export */
// Removes double quotes on ETags from S3
export function santizeETag(tag: string): string {
return tag.replace(/"/g, '');
}

View File

@@ -11,16 +11,20 @@
import path from 'path';
import * as fs from 'fs';
import { spawn } from 'child_process';
import { app, BrowserWindow, shell, ipcMain, globalShortcut } from 'electron';
// import { autoUpdater } from 'electron-updater';
import log from 'electron-log';
// import MenuBuilder from './menu';
import { resolveHtmlPath } from './util';
import FileManager from './libs';
import { app, BrowserWindow, shell, ipcMain, globalShortcut } from 'electron';
// Types
import Channels from '../constants';
// Typings, Interfaces, and Constants
import { LauncherServer } from 'typings';
import Downloader from './libs/Downloader';
import { Channels } from '../constants';
// import { autoUpdater } from 'electron-updater';
import MenuBuilder from './menu';
import { resolveHtmlPath } from './util';
import FileManager from './libs/FileManager';
const showdown = require('showdown');
// class AppUpdater {
// constructor() {
@@ -32,113 +36,14 @@ import Channels from '../constants';
let mainWindow: BrowserWindow | null = null;
/**
* Server Preload Events to gather information about the environment before the UI launches
*/
// loads the application path where the exe is run, this is needed to lookup information about the installed patches.
let appPath: string;
let fileManager: FileManager;
if (process.platform === 'win32') {
if(process.env.PORTABLE_EXECUTABLE_DIR) {
appPath = path.join(process.env.PORTABLE_EXECUTABLE_DIR, 'Wow.exe')
fileManager = new FileManager(process.env.PORTABLE_EXECUTABLE_DIR || '')
} else {
appPath = path.join(__dirname, '../../mockGame','Wow.exe');
fileManager = new FileManager(path.join(__dirname, '../../mockGame'));
}
} else {
appPath = '/System/Applications/Chess.app';
fileManager = new FileManager(path.join(__dirname, '../../dist/')); // will handle macs even though we will never be building for one.
}
/**
* This will return all the information of the file system installed in the directory.
*/
ipcMain.handle(Channels.APP_INFO, async () => {
const appInfo = {
version: '3.3.5 (v1)',
credits: 'ben-of-codecraft',
lastupdate: '2023-09-03',
execpath: process.env.PORTABLE_EXECUTABLE_DIR,
HD: await fileManager.IsHDSetup(),
HDExtra: await fileManager.IsHDExtraSetup(),
Misc: await fileManager.IsMiscSetup(),
Araxia: await fileManager.IsAraxiaSetup(),
WoWInstalled: await fileManager.IsWoWInstalled(),
WoWPatched: await fileManager.IsWoWPatched(),
AIOInstalled: await fileManager.IsAIOInstalled(),
};
console.log('App Info: ', appInfo);
return appInfo;
});
ipcMain.on(Channels.WOW_LAUNCH, (event, arg) => {
if (!fs.existsSync(appPath)) {
event.reply(Channels.WOW_LAUNCH_ERROR, {
type: 'FileError',
message: `WoW application not found or permissions are not set to readable: ${appPath}`,
} as ErrorEvent);
}
let childProcess;
if (process.platform === 'darwin') {
childProcess = spawn('open', [appPath]);
} else {
childProcess = spawn(appPath);
}
childProcess.on('close', (code) => {
console.info(`WoW client exited with code: ${code}`);
});
childProcess.on('exit', () => {
console.info('WoW client exited');
});
childProcess.on('exit', () => {
console.info('Child process is launched closing window');
// event.reply(Channels.WOW_CLIENT_EXIT);
mainWindow?.close();
});
mainWindow?.close();
});
if (process.env.NODE_ENV === 'production') {
const sourceMapSupport = require('source-map-support');
sourceMapSupport.install();
}
const isDebug =
process.env.NODE_ENV === 'development' || process.env.DEBUG_PROD === 'true';
// if (isDebug || true) {
// require('electron-debug')();
// }
// const installExtensions = async () => {
// const installer = require('electron-devtools-installer');
// const forceDownload = !!process.env.UPGRADE_EXTENSIONS;
// const extensions = ['REACT_DEVELOPER_TOOLS'];
// return installer
// .default(
// extensions.map((name) => installer[name]),
// forceDownload
// )
// .catch(console.log);
// };
const isDebug = process.env.NODE_ENV === 'development' || process.env.DEBUG_PROD === 'true';
const createWindow = async () => {
if (isDebug) {
// await installExtensions();
}
const RESOURCES_PATH = app.isPackaged
? path.join(process.resourcesPath, 'assets')
@@ -157,7 +62,8 @@ const createWindow = async () => {
preload: app.isPackaged
? path.join(__dirname, 'preload.js')
: path.join(__dirname, '../../.erb/dll/preload.js'),
nodeIntegration: true,
nodeIntegration: false,
sandbox: false
},
});
@@ -178,8 +84,9 @@ const createWindow = async () => {
mainWindow = null;
});
// const menuBuilder = new MenuBuilder(mainWindow);
// menuBuilder.buildMenu();
const menuBuilder = new MenuBuilder(mainWindow);
menuBuilder.buildMenu();
// Open urls in the user's browser
mainWindow.webContents.setWindowOpenHandler((edata) => {
@@ -219,3 +126,187 @@ app
});
})
.catch(console.log);
/** ************************************************
* Event Management for IPC
************************************************* */
// loads the application path where the exe is run, this is needed to lookup information about the installed patches.
let appPath: string;
let fileManager: FileManager;
if (process.platform === 'win32') {
if(process.env.PORTABLE_EXECUTABLE_DIR) {
appPath = path.join(process.env.PORTABLE_EXECUTABLE_DIR, 'Wow.exe')
fileManager = new FileManager(process.env.PORTABLE_EXECUTABLE_DIR || '')
} else {
appPath = path.join(__dirname, '../../mockGame','Wow.exe');
fileManager = new FileManager(path.join(__dirname, '../../mockGame'));
}
} else {
appPath = '/System/Applications/Chess.app';
fileManager = new FileManager(path.join(__dirname, '../../dist/')); // will handle macs even though we will never be building for one.
}
/**
* This will return all the information of the file system installed in the directory.
*/
ipcMain.handle(Channels.APP_INFO, async () => {
const version = await fileManager.GetVersion();
// Get the news and convert it to html
const news = await fileManager.GetLatestNews();
const converter = new showdown.Converter();
const newHtml = converter.makeHtml(news);
const remoteInfo = await fileManager.GetRemoteVersion();
const localInfo = await fileManager.GetVersion();
const appInfo = {
Version: localInfo.Version,
LastUpdate: localInfo.LastUpdate,
ExecPath: process.env.PORTABLE_EXECUTABLE_DIR,
HD: await fileManager.IsHDSetup(),
Misc: await fileManager.IsMiscSetup(),
WoWInstalled: await fileManager.IsWoWInstalled(),
WoWPatched: await fileManager.IsWoWPatched(),
AIOInstalled: await fileManager.IsAIOInstalled(),
LatestNews: newHtml,
RemoteVersion: remoteInfo[0]?.version,
};
return appInfo;
});
(async () => {
// const remoteInfo = await fileManager.GetRemoteVersion();
// const custom = await fileManager.GetCustomFiles();
// console.log(custom);
})();
/**
* We have to redirect events from the main process to the render process as they are fired this allows the
* frontend to attach the backend event listeners, complex objects can not be handled by ipcRenderer.
* @param downloader
*/
function passthrough(downloader: Downloader) {
downloader.on('start', (event) => {
try {
mainWindow?.webContents.send(Channels.DOWNLOAD_START, {
totalBytes: event.totalBytes,
remoteFile: event.remoteFile
});
} catch (error: any) {
console.log(error.message);
}
});
downloader.on('data', (event) => {
mainWindow?.webContents.send(Channels.DOWNLOAD_PROGRESS, event);
});
downloader.on('end', (event) => {
mainWindow?.webContents.send(Channels.DOWNLOAD_END, event);
});
downloader.on('batchStart', (event) => {
mainWindow?.webContents.send(Channels.DOWNLOAD_BATCH_START, event);
});
downloader.on('batchData', (event) => {
mainWindow?.webContents.send(Channels.DOWNLOAD_BATCH_DATA, event);
});
downloader.on('batchEnd', (event) => {
mainWindow?.webContents.send(Channels.DOWNLOAD_BATCH_END, event);
});
}
/**
* Main Calls to backend Filemanager
*/
ipcMain.handle(Channels.APP_API, async (event, method: LauncherServer.Methods, ...args) => {
switch (method) {
case 'GetInstalledPatches': {
// return await fileManager.GetInstalledPatches(args[0]);
break;
}
case 'InstallAIO': {
const result = await fileManager.InstallAIO();
if(result instanceof Downloader) {
passthrough(result);
}
break;
}
case 'PatchWow': {
const result = await fileManager.PatchWowExe();
return true;
}
case 'InstallHD': {
const result = await fileManager.InstallPatches('hd');
if(result instanceof Downloader) {
passthrough(result);
}
break;
}
case 'InstallMisc': {
const result = await fileManager.InstallPatches('misc');
if(result instanceof Downloader) {
passthrough(result);
}
break;
}
case 'InstallUpdates': {
const result = await fileManager.InstallUpdates();
if(result instanceof Downloader) {
passthrough(result);
}
break;
}
default:
log.error(`Unknown method: ${method}`);
break;
}
return null;
});
ipcMain.on(Channels.WOW_LAUNCH, (event, arg) => {
if (!fs.existsSync(appPath)) {
event.reply(Channels.WOW_LAUNCH_ERROR, {
type: 'FileError',
message: `WoW application not found or permissions are not set to readable: ${appPath}`,
} as ErrorEvent);
console.error(`WoW application not found or permissions are not set to readable: ${appPath}`);
}
if(!app.isPackaged) {
// appPath = "C:\\Users\\benca\\Desktop\\WoW\\WorldOfWarcraft_3.3.5a-unpatched\\Wow.exe";
}
console.log(`Launching WoW client: ${appPath}`);
const childProcess = spawn(appPath, {
detached: true
});
childProcess.on('close', (code) => {
console.info(`WoW client exited with code: ${code}`);
});
childProcess.on('error', (err) => {
console.log(err);
});
setTimeout(() => {
mainWindow?.close();
}, 1000);
});

View File

@@ -3,13 +3,11 @@ import {
Menu,
shell,
BrowserWindow,
MenuItemConstructorOptions,
dialog
} from 'electron';
interface DarwinMenuItemConstructorOptions extends MenuItemConstructorOptions {
selector?: string;
submenu?: DarwinMenuItemConstructorOptions[] | Menu;
}
import path from 'path';
import packageJson from '../../package.json';
export default class MenuBuilder {
mainWindow: BrowserWindow;
@@ -26,11 +24,7 @@ export default class MenuBuilder {
this.setupDevelopmentEnvironment();
}
const template =
process.platform === 'darwin'
? this.buildDarwinTemplate()
: this.buildDefaultTemplate();
const template = this.buildDefaultTemplate();
const menu = Menu.buildFromTemplate(template);
Menu.setApplicationMenu(menu);
@@ -52,155 +46,11 @@ export default class MenuBuilder {
});
}
buildDarwinTemplate(): MenuItemConstructorOptions[] {
const subMenuAbout: DarwinMenuItemConstructorOptions = {
label: 'Electron',
submenu: [
{
label: 'About ElectronReact',
selector: 'orderFrontStandardAboutPanel:',
},
{ type: 'separator' },
{ label: 'Services', submenu: [] },
{ type: 'separator' },
{
label: 'Hide ElectronReact',
accelerator: 'Command+H',
selector: 'hide:',
},
{
label: 'Hide Others',
accelerator: 'Command+Shift+H',
selector: 'hideOtherApplications:',
},
{ label: 'Show All', selector: 'unhideAllApplications:' },
{ type: 'separator' },
{
label: 'Quit',
accelerator: 'Command+Q',
click: () => {
app.quit();
},
},
],
};
const subMenuEdit: DarwinMenuItemConstructorOptions = {
label: 'Edit',
submenu: [
{ label: 'Undo', accelerator: 'Command+Z', selector: 'undo:' },
{ label: 'Redo', accelerator: 'Shift+Command+Z', selector: 'redo:' },
{ type: 'separator' },
{ label: 'Cut', accelerator: 'Command+X', selector: 'cut:' },
{ label: 'Copy', accelerator: 'Command+C', selector: 'copy:' },
{ label: 'Paste', accelerator: 'Command+V', selector: 'paste:' },
{
label: 'Select All',
accelerator: 'Command+A',
selector: 'selectAll:',
},
],
};
const subMenuViewDev: MenuItemConstructorOptions = {
label: 'View',
submenu: [
{
label: 'Reload',
accelerator: 'Command+R',
click: () => {
this.mainWindow.webContents.reload();
},
},
{
label: 'Toggle Full Screen',
accelerator: 'Ctrl+Command+F',
click: () => {
this.mainWindow.setFullScreen(!this.mainWindow.isFullScreen());
},
},
{
label: 'Toggle Developer Tools',
accelerator: 'Alt+Command+I',
click: () => {
this.mainWindow.webContents.toggleDevTools();
},
},
],
};
const subMenuViewProd: MenuItemConstructorOptions = {
label: 'View',
submenu: [
{
label: 'Toggle Full Screen',
accelerator: 'Ctrl+Command+F',
click: () => {
this.mainWindow.setFullScreen(!this.mainWindow.isFullScreen());
},
},
],
};
const subMenuWindow: DarwinMenuItemConstructorOptions = {
label: 'Window',
submenu: [
{
label: 'Minimize',
accelerator: 'Command+M',
selector: 'performMiniaturize:',
},
{ label: 'Close', accelerator: 'Command+W', selector: 'performClose:' },
{ type: 'separator' },
{ label: 'Bring All to Front', selector: 'arrangeInFront:' },
],
};
const subMenuHelp: MenuItemConstructorOptions = {
label: 'Help',
submenu: [
{
label: 'Learn More',
click() {
shell.openExternal('https://electronjs.org');
},
},
{
label: 'Documentation',
click() {
shell.openExternal(
'https://github.com/electron/electron/tree/main/docs#readme'
);
},
},
{
label: 'Community Discussions',
click() {
shell.openExternal('https://www.electronjs.org/community');
},
},
{
label: 'Search Issues',
click() {
shell.openExternal('https://github.com/electron/electron/issues');
},
},
],
};
const subMenuView =
process.env.NODE_ENV === 'development' ||
process.env.DEBUG_PROD === 'true'
? subMenuViewDev
: subMenuViewProd;
return [subMenuAbout, subMenuEdit, subMenuView, subMenuWindow, subMenuHelp];
}
buildDefaultTemplate() {
const templateDefault = [
{
label: '&File',
submenu: [
{
label: '&Open',
accelerator: 'Ctrl+O',
},
{
label: '&Close',
accelerator: 'Ctrl+W',
@@ -212,75 +62,46 @@ export default class MenuBuilder {
},
{
label: '&View',
submenu:
process.env.NODE_ENV === 'development' ||
process.env.DEBUG_PROD === 'true'
? [
{
label: '&Reload',
accelerator: 'Ctrl+R',
click: () => {
this.mainWindow.webContents.reload();
},
},
{
label: 'Toggle &Full Screen',
accelerator: 'F11',
click: () => {
this.mainWindow.setFullScreen(
!this.mainWindow.isFullScreen()
);
},
},
{
label: 'Toggle &Developer Tools',
accelerator: 'Alt+Ctrl+I',
click: () => {
this.mainWindow.webContents.toggleDevTools();
},
},
]
: [
{
label: 'Toggle &Full Screen',
accelerator: 'F11',
click: () => {
this.mainWindow.setFullScreen(
!this.mainWindow.isFullScreen()
);
},
},
],
},
{
label: 'Help',
submenu: [
{
label: 'Learn More',
click() {
shell.openExternal('https://electronjs.org');
label: '&Reload',
accelerator: 'Ctrl+R',
click: () => {
this.mainWindow.webContents.reload();
},
},
{
label: 'Documentation',
label: 'Toggle &Developer Tools',
accelerator: 'Alt+Ctrl+I',
click: () => {
this.mainWindow.webContents.toggleDevTools();
},
},
],
},
{
label: 'About',
submenu: [
{
label: 'Araxia Client Patcher',
click() {
dialog.showMessageBox({
title: 'About',
message: `Araxia Client Patcher v${packageJson.version}`,
detail: "Credits:\nProgramming and Design: Ben Carter @ben-of-codecraft \nPatch Master: Eric Gates @manmadedrummer\nInfrastructure: Chris Turley @wonderboy",
buttons: ['OK'],
icon: path.join(__dirname, '../../assets', 'wow-icon.png')
})
},
},
{
label: 'GitHub',
click() {
shell.openExternal(
'https://github.com/electron/electron/tree/main/docs#readme'
'https://github.com/araxiaonline'
);
},
},
{
label: 'Community Discussions',
click() {
shell.openExternal('https://www.electronjs.org/community');
},
},
{
label: 'Search Issues',
click() {
shell.openExternal('https://github.com/electron/electron/issues');
},
},
],
},
];

View File

@@ -1,23 +1,86 @@
/* eslint-disable no-console */
import { contextBridge, ipcRenderer } from 'electron';
import log from 'electron-log';
import Channels from '../constants';
import { LauncherServer } from '../typings';
import { Channels } from '../constants';
import { LauncherServer, DownloadCallbacks } from '../typings';
function apiCaller(method: LauncherServer.Methods, ...args: any[]): Promise<any>{
return ipcRenderer.invoke(Channels.APP_API, method, ...args);
}
/**
* Wrapper around the ipcRenderer to handle the download events
* Since you can not
* ss complex object through the IPC Channel this is used
* to relay the results of downloads happening on the server to the renderer.
*
* Every download that is requested by the users will track status on these channels.
*/
class DownloadListener {
constructor(callbacks: DownloadCallbacks) {
ipcRenderer.on(Channels.DOWNLOAD_START, (event, args ) => {
callbacks.start?.({
totalBytes: args.total,
remoteFile: args.files
});
});
ipcRenderer.on(Channels.DOWNLOAD_END, (event, args ) => {
callbacks.end?.(args);
});
ipcRenderer.on(Channels.DOWNLOAD_PROGRESS, (event, args ) => {
callbacks.data?.(args);
});
ipcRenderer.on(Channels.DOWNLOAD_BATCH_START, (event, args ) => {
callbacks.batchStart?.(args);
});
ipcRenderer.on(Channels.DOWNLOAD_BATCH_END, (event, args ) => {
callbacks.batchEnd?.(args);
});
ipcRenderer.on(Channels.DOWNLOAD_BATCH_DATA, (event, args ) => {
callbacks.batchData?.(args);
});
}
}
const handleInstall = async (apiMethodName: LauncherServer.Methods, callbacks: DownloadCallbacks) => {
// this registers callbacks on the object
const downloadListener = new DownloadListener(callbacks);
try {
await apiCaller(apiMethodName);
} catch (error: any) {
const msg = `Install Error: getting install details: ${error.message}`;
return {
type: 'Install',
message: msg,
} as ErrorEvent;
}
return null;
};
/**
* All the API's exposed to the renderer process
*/
const IPCApi: LauncherServer.Api = {
Launch: () => {
console.info('Launching WoW client');
ipcRenderer.send(Channels.WOW_LAUNCH);
},
OnExitApp: (handler) => {
ipcRenderer.on(Channels.WOW_CLIENT_EXIT, handler);
},
OnLaunchError: (handler) => {
ipcRenderer.on(
Channels.WOW_LAUNCH_ERROR,
(event: any, error: ErrorEvent) => {
log.info(
console.info(
`WoW client exited with Error: [${error.type}]: ${error.message}`
);
handler(event, error);
@@ -31,7 +94,7 @@ const IPCApi: LauncherServer.Api = {
return appInfo;
} catch (error: any) {
const msg = `Error getting app info: ${error}`;
log.error(msg);
console.error(msg);
return {
type: 'Parse',
@@ -49,13 +112,32 @@ const IPCApi: LauncherServer.Api = {
return installDetails;
} catch (error: any) {
const msg = `Error getting install details: ${error}`;
log.error(msg);
console.error(msg);
return {
type: 'Parse',
message: msg,
} as ErrorEvent;
}
},
InstallStore: async (callbacks: DownloadCallbacks) => {
await handleInstall('InstallAIO', callbacks);
},
PatchWoW: async () => {
await handleInstall('PatchWow', {});
},
InstallHD: async (callbacks: DownloadCallbacks) => {
await handleInstall('InstallHD', callbacks);
},
InstallMisc: async (callbacks: DownloadCallbacks) => {
handleInstall('InstallMisc', callbacks);
},
InstallUpdates: async (callbacks: DownloadCallbacks) => {
handleInstall('InstallUpdates', callbacks);
}
};

View File

@@ -11,3 +11,12 @@ export function resolveHtmlPath(htmlFileName: string) {
}
return `file://${path.resolve(__dirname, '../renderer/', htmlFileName)}`;
}
export function byteToMbs(bytes: number): number {
return +(bytes/1024/1024).toFixed(2);
}
// Removes double quotes on ETags from S3
export function santizeETag(tag: string): string {
return tag.replace(/"/g, '');
}

155
src/typings/index.d.ts vendored
View File

@@ -1,4 +1,5 @@
import { IpcRendererEvent } from 'electron';
import { DownloadEventMap } from 'main/libs/Downloader';
declare global {
/**
@@ -10,15 +11,11 @@ declare global {
}
}
/**
* Used to delcare file types to TypeScript that are not modules
*/
declare module '*.png';
declare module '*.jpeg';
declare module '*.mp3' {
const value: any;
export default value;
}
type Callbacks<T> = {
[K in keyof T]?: (params: T[K]) => void;
};
export type DownloadCallbacks = Callbacks<DownloadEventMap>;
declare namespace WowLauncher {
/*
@@ -28,55 +25,57 @@ declare namespace WowLauncher {
/**
* The current version of the application.
*/
version: string;
/**
* Contributors to the application and their contributions.
*/
credits: string;
Version: string;
/**
* The last time the application was updated.
*/
lastupdate: string;
LastUpdate: string;
/**
* The original path to the executable of the application. This is different
* than a potentially temporary path where the actual exe runs; this is the directory
* where the exe is located. This is used to communicate with the external WoW exe
* and collect information about the installed WoW client.
*/
execpath: string;
/**
* Manifest of files on host machine
*/
manifest: Manifest;
ExecPath: string;
/**
* Whether or not the HD patch is installed.
*/
HD: boolean;
/**
* Whether or not the HD Extra patch is installed.
*/
HDExtra: boolean;
/**
* Whether or not the Fearure patches are installed
*/
Features: boolean;
Misc: boolean;
/**
* Whether or not Araxia patches are installed.
*/
Araxia: boolean;
}
interface Manifest {
/**
* List of files currently present on the user's machine that are not part of the vanilla installation.
* from ChromieCraft. <https://www.chromiecraft.com/en/downloads/>
* Whether or not the WoW client is installed.
*/
patchfiles: PatchFile[];
WoWInstalled: boolean;
/**
* Last time the manifest was updated.
* Whether or not the WoW client is patched.
*/
lastupdate: string;
WoWPatched: boolean;
/**
* Whether or not the AIO patch is installed.
*/
AIOInstalled: boolean;
/**
* The latest news about the application.
*/
LatestNews: string;
/**
* The remote version of the client.
*/
RemoteVersion: string;
}
interface PatchFile {
@@ -120,6 +119,45 @@ declare namespace LauncherServer {
* If not detected, the version returned is "3.3.5a-v0" (the base version of the client).
*/
GetAppInfo: () => Promise<WowLauncher.AppInfo | null>;
/**
* Patches the server Wow.exe with the patched version if needed.
*/
PatchWoW: () => void;
/**
* Returns the list of files that are currently installed on the user's machine.
*/
GetInstalledPatches(type: string): Promise<WowLauncher.PatchFile[] | null>;
/**
*
* @param callbacks Installs addon required to login to the store.
* @returns
*/
InstallStore: (callbacks: any) => void;
/**
* Install HD patches from server
* @param callbacks
* @returns
*/
InstallHD: (callbacks: any) => void;
/**
* Installs Misc patches from server
* @param callbacks
* @returns
*/
InstallMisc: (callbacks: any) => void;
/**
* Installs custom content updates from server
* @param callbacks
* @returns
*/
InstallUpdates: (callbacks: any) => void;
}
/**
@@ -136,35 +174,34 @@ declare namespace LauncherServer {
type: 'File' | 'Request' | 'Generic' | 'Parse';
message: string;
}
type Methods =
'InstallAIO' |
'GetInstalledPatches' |
'PatchWow' |
'InstallHD' |
'InstallMisc' |
'GetRemoteVersion' |
'InstallUpdates';
}
declare namespace LauncherUI {
/**
* List of files and tags showing last time they were changed. Additionally, this
* is used to determine the current version of the client.
*/
declare interface Manifest {
/**
* Server response data to server about the latest information about the client patches.
* The version the current client with patching
*/
interface RemoteServer {
/**
* Server patch version.
*/
version: string;
/**
* List of changes made in the patch.
*/
changelog: string[];
/**
* Date the patch was released.
*/
date: string;
/**
* Who made the patch.
*/
updatedby: string;
/**
* List of files that were changed in the patch. That need to be downloaded
* and replaced on the client.
*/
filelist: string[];
}
Version: string;
/**
* List of files currently present on the user's machine that are not part of the vanilla installation.
*/
Files: Record<string, any>;
/**
* Last time the manifest was updated.
*/
LastUpdate: string;
}
export { LauncherServer, LauncherUI, WowLauncher };
export { LauncherServer, WowLauncher, Manifest };