electric-games/main.js

182 lines
No EOL
5.2 KiB
JavaScript

const { app, BrowserWindow, ipcMain, dialog } = require('electron');
const fs = require('fs');
const path = require('path');
const AdmZip = require('adm-zip'); // For ZIP extraction
const { promisify } = require('util');
const readdir = promisify(fs.readdir);
const stat = promisify(fs.stat);
const { exec } = require('child_process');
let mainWindow;
function createWindow() {
mainWindow = new BrowserWindow({
width: 1000,
height: 800,
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
webviewTag: true, // Make sure webview is enabled
}
});
mainWindow.loadFile('index.html');
}
app.whenReady().then(() => {
createWindow();
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
});
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
// Function to download and extract ZIP files
ipcMain.handle('download-and-extract', async (event, downloadUrl, libraryFolder, fileName) => {
try {
const downloadPath = path.join(libraryFolder, fileName);
// Start downloading the game from the URL
const response = await fetch(downloadUrl);
if (!response.ok) throw new Error('Download failed');
const buffer = await response.arrayBuffer();
const fileBuffer = Buffer.from(buffer);
// Write the downloaded zip file to disk
fs.writeFileSync(downloadPath, fileBuffer);
// Now extract the downloaded ZIP
await extractZip(downloadPath, libraryFolder);
// Return the path to the extracted folder
return { success: true, folderPath: libraryFolder };
} catch (error) {
console.error('Error during download or extraction:', error);
return { success: false, error: error.message };
}
});
// Function to extract ZIP files
async function extractZip(zipPath, extractToFolder) {
try {
const zip = new AdmZip(zipPath);
zip.extractAllTo(extractToFolder, true);
console.log(`Extracted ZIP to ${extractToFolder}`);
// Clean up the ZIP file after extraction
fs.unlinkSync(zipPath); // Delete the ZIP file
} catch (error) {
console.error('Error extracting ZIP:', error);
throw new Error('Error extracting ZIP');
}
}
// Scan for .exe files in the Library folder (excluding `redist` folders)
ipcMain.handle('scan-library', async (event, libraryFolder) => {
try {
const gameExecutables = await scanForExecutables(libraryFolder);
return gameExecutables;
} catch (error) {
console.error('Error scanning library:', error);
return [];
}
});
async function scanForExecutables(directory) {
console.log(directory.exeFiles)
return directory.exeFiles;
}
module.exports = { scanForExecutables };
// Handle the Wine binary selection
ipcMain.handle('select-wine-binary', async () => {
const result = await dialog.showOpenDialog({
properties: ['openFile'],
filters: [{ name: 'Executables', extensions: ['exe'] }],
});
if (result.canceled || result.filePaths.length === 0) {
return null;
}
winePath = result.filePaths[0]; // Store the path to the Wine binary
return winePath;
});
// Handle the selection of a Library folder and get list of `.exe` files
ipcMain.handle('select-library-folder', async () => {
const result = await dialog.showOpenDialog({
properties: ['openDirectory'],
});
if (result.canceled || result.filePaths.length === 0) {
return null;
}
const libraryFolderPath = result.filePaths[0];
const exeFiles = await scanDirectory(libraryFolderPath); // Scan the folder for .exe files
return { libraryFolderPath, exeFiles };
});
// Recursive function to scan a directory for `.exe` files
async function scanDirectory(dirPath) {
const exeFiles = [];
const files = await fs.promises.readdir(dirPath, { withFileTypes: true });
for (const file of files) {
const fullPath = path.join(dirPath, file.name);
if (file.isDirectory()) {
// Recursively scan subdirectories
const subDirFiles = await scanDirectory(fullPath);
exeFiles.push(...subDirFiles);
} else if (file.isFile() && file.name.toLowerCase().endsWith('.exe')) {
// Add `.exe` files to the list
exeFiles.push(fullPath);
}
}
return exeFiles;
}
// Handle running the game via Wine
ipcMain.handle('run-game-with-wine', async (event, gameExePath) => {
if (!winePath) {
return { success: false, message: 'Wine binary not selected' };
}
try {
await runWineCommand(winePath, gameExePath);
return { success: true };
} catch (error) {
return { success: false, message: error.message };
}
});
// Helper function to execute Wine command
function runWineCommand(wineBinary, gameExePath) {
return new Promise((resolve, reject) => {
const command = `"${wineBinary}" "${gameExePath}"`;
exec(command, (error, stdout, stderr) => {
if (error) {
reject(new Error(`Error running Wine command: ${stderr || stdout}`));
} else {
resolve(stdout);
}
});
});
}