Skip to content

Commit

Permalink
using custom java runtime, appending to singular logfile
Browse files Browse the repository at this point in the history
- using adoptium temurin java runtime for both client and server installations
- no longer creating multiple logfiles if installer is used more than once, just appends to existing
- removed java installation checks
- added java/w executable paths to state store
- added tar package for archive extraction on unix systems
  • Loading branch information
jgaribsin committed Feb 5, 2024
1 parent 8e41bcb commit 3495f89
Show file tree
Hide file tree
Showing 12 changed files with 241 additions and 205 deletions.
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "drehmal-installer",
"version": "0.2.0",
"version": "0.3.0",
"description": "Drehmal, Minecraft map installer",
"productName": "Drehmal Installer",
"author": "jgaribsin",
Expand All @@ -27,6 +27,7 @@
"extract-zip": "^2.0.1",
"pinia": "^2.0.11",
"quasar": "^2.14.2",
"tar": "^6.2.0",
"vue": "^3.0.0",
"vue-i18n": "^9.2.2",
"vue-router": "^4.0.0"
Expand All @@ -35,6 +36,7 @@
"@intlify/vite-plugin-vue-i18n": "^3.3.1",
"@quasar/app-vite": "^1.3.0",
"@types/node": "^12.20.21",
"@types/tar": "^6.1.11",
"@typescript-eslint/eslint-plugin": "^5.10.0",
"@typescript-eslint/parser": "^5.10.0",
"autoprefixer": "^10.4.2",
Expand Down
15 changes: 2 additions & 13 deletions src-electron/electron-main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import log from 'electron-log';
import Listeners from './ipcListeners';
const path = require('path');
const os = require('os');
const fs = require('fs');

import { version } from '../package.json';

Expand All @@ -18,18 +17,8 @@ const logFolder = path.join(
'logs'
);

const getLogFileName: () => string = () => {
let index = 1;
let name = `${currDate}_${index}-installer.log`;
while (true) {
if (!fs.existsSync(path.join(logFolder, name))) break;
else name = `${currDate}_${index++}-installer.log`;
}
return name;
};
// can't use function call in resolve path as it'll create a new file for each logger instance
const logFileName = getLogFileName();
log.transports.file.resolvePathFn = () => path.join(logFolder, logFileName);
log.transports.file.resolvePathFn = () =>
path.join(logFolder, `${currDate}-installer.log`);
log.transports.file.format = '[{h}:{i}:{s}.{ms}] [{level}] {text}';

// initialise logger for uncaught execptions
Expand Down
71 changes: 10 additions & 61 deletions src-electron/ipcListeners.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,34 +28,16 @@ export default class Listeners {
dialog = electronDialog;

browserWindow.webContents.on('will-navigate', (event, url) => {
if (url.startsWith('open-java-page://')) {
event.preventDefault();
shell.openExternal('https://www.java.com/en/download/manual.jsp');
} else if (url.startsWith('open-jdk-page://')) {
event.preventDefault();
switch (process.platform) {
case 'win32':
shell.openExternal(
'https://www.oracle.com/java/technologies/downloads/#jdk21-windows'
);
break;
case 'darwin':
shell.openExternal(
'https://www.oracle.com/java/technologies/downloads/#jdk21-mac'
);
break;
case 'linux':
shell.openExternal(
'https://www.oracle.com/java/technologies/downloads/#jdk21-linux'
);
break;
default:
shell.openExternal(
'https://www.oracle.com/java/technologies/downloads/#java21'
);
break;
}
}
// For custom URLs, use the following (must be above generic openExternal)
// if (url.startsWith('open-java-page://')) {
// event.preventDefault();
// shell.openExternal('https://www.java.com/en/download/manual.jsp');
// }
// Will be used with: <a href="open-java-page://">Java Downloads Page</a>

// To open URLs in an external browser
event.preventDefault();
shell.openExternal(url);
});
}
}
Expand Down Expand Up @@ -132,40 +114,7 @@ ipcMain.handle(
})
);

ipcMain.handle('checkJava', () => {
return new Promise((resolve, reject) => {
exec(
'java -version',
(error: Error | null, stdout: string, stderr: string) => {
if (error) reject(error);
else resolve(stdout || stderr);
}
);
});
});

ipcMain.handle('execute', (_event, cmd) => {
console.log(`Executing command: ${cmd}`);
exec(cmd);
});

ipcMain.handle(
'checkJDK',
() =>
new Promise<number | string>((resolve) => {
exec(
'java -version',
(error: Error | null, stdout: string, stderr: string) => {
if (error) resolve(0); // Resolve with 0 on error
else {
const match = stderr.match(/version "(.*?)"/);
const javaVersion = match ? match[1] : null;
console.log(`Java Version found: ${javaVersion}!`);
if (javaVersion)
resolve(parseInt(javaVersion)); // Resolve with the JDK version
else resolve(0); // Resolve with 0 if the version cannot be determined
}
}
);
})
);
2 changes: 1 addition & 1 deletion src/components/CloseInstaller.vue
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ const click = () => {
if (launchButton.value === true && installType.value !== 'server') {
if (platform.value === 'win32') {
console.log(
`Launching Minecraft on ${platform.value} with file: ${windowsPath}`
`Launching Minecraft on ${platform.value} with file: "${windowsPath}"`
);
ipcRenderer.invoke('minecraftWin', windowsPath).then(() => {
console.log('Minecraft launched, exiting...');
Expand Down
37 changes: 1 addition & 36 deletions src/components/ServerPath.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@

<script setup lang="ts">
import { storeToRefs } from 'pinia';
import { useQuasar } from 'quasar';
import { useInstallerStore } from 'src/stores/InstallerStore';
import { onMounted, ref } from 'vue';
import { ref } from 'vue';
const { ipcRenderer } = require('electron');
const { serverDir } = storeToRefs(useInstallerStore());
Expand All @@ -37,40 +36,6 @@ const folderSelectChange = async () => {
console.log(`Server Path updated to "${serverDir.value}"`);
}
};
const q = useQuasar();
async function checkJDK() {
const platform = await ipcRenderer.invoke('getPlatformPretty');
const arch = await ipcRenderer.invoke('getArch');
// Verify the user has the right JDK version installed, otherwise prevent them from continuing
let jdkVersion = 0;
const jdkRequired = 17;
// servers require jdk version 17 or above, loop until that's found
while (jdkVersion < jdkRequired) {
// check java installation
jdkVersion = await ipcRenderer.invoke('checkJDK');
if (jdkVersion <= jdkRequired)
await new Promise<void>((resolve) => {
q.dialog({
title: 'JDK not installed',
// allow html in dialog message
html: true,
// provide user with their current OS type and architecture, then provide a link to the java downloads page
message:
'The required JDK version is not installed on your system.' +
` Please download the installer for <span style="color: #ffde00;"><strong>${platform}-${arch}</strong></span> and install it.<br/><br/>` +
'<a href="open-jdk-page://">JDK Downloads Page</a><br/><br/>' +
'After installing, click the button below.',
ok: 'I have installed the JDK', // text for the ok button
persistent: true,
dark: true,
}).onOk(() => resolve()); // resolve promise on ok button click
});
}
}
onMounted(checkJDK);
</script>

<style scoped>
Expand Down
42 changes: 0 additions & 42 deletions src/pages/InstallationType.vue
Original file line number Diff line number Diff line change
Expand Up @@ -69,52 +69,10 @@
</template>

<script setup lang="ts">
const { ipcRenderer } = require('electron');
import { storeToRefs } from 'pinia';
import { useQuasar } from 'quasar';
import { useStateStore } from 'src/stores/StateStore';
import { onMounted } from 'vue';
const { installType } = storeToRefs(useStateStore());
const q = useQuasar();
async function checkJavaInstallation() {
const platform = await ipcRenderer.invoke('getPlatformPretty');
const arch = await ipcRenderer.invoke('getArch');
// Verify the user has java installed, otherwise prevent them from continuing
let javaCheckResult = false;
// Loop until java installation is verified
while (!javaCheckResult) {
try {
// check java installation
await ipcRenderer.invoke('checkJava');
javaCheckResult = true;
} catch (error) {
// 'checkJava' throws an error if java is not installed (fails to run 'java -version')
// await a new promise until user clicks ok, otherwise the dialog is spammed
await new Promise<void>((resolve) => {
q.dialog({
title: 'Java not installed',
// allow html in dialog message
html: true,
// provide user with their current OS type and architecture, then provide a link to the java downloads page
message:
'Java is not installed on your system.' +
` Please download the installer for <span style="color: #ffde00;"><strong>${platform}-${arch}</strong></span> and install it.<br/><br/>` +
'<a href="open-java-page://">Java Downloads Page</a><br/><br/>' +
'After installing, click the button below.',
ok: 'I have installed Java', // text for the ok button
persistent: true,
dark: true,
}).onOk(() => resolve()); // resolve promise on ok button click
});
}
}
}
onMounted(checkJavaInstallation);
</script>

<style scoped>
Expand Down
9 changes: 5 additions & 4 deletions src/providers/DownloadFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@ export function downloadFile(
file.on('error', (err: any) => {
console.error(`file error on ${name} ${url}`, err);
});

// User-Agent: github_username/project_name/1.56.0 (launcher.com)
const options = {
// headers: {
// 'accept-encoding': 'gzip, deflate, br',
// },
headers: {
'User-Agent': 'Drehmal-Team/installer/0.2.0 (drehmal.net)',
// 'accept-encoding': 'gzip, deflate, br',
},
};
https.get(url, options).on('response', function (res: any) {
// const startTime = Date.now();
Expand Down
20 changes: 14 additions & 6 deletions src/providers/InstallFabric.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { useSourcesStore } from 'src/stores/SourcesStore';
import { useStateStore } from 'src/stores/StateStore';
import { Ref } from 'vue';
import { downloadFile } from './DownloadFile';
import { getJre } from './JavaDownload';
const { spawn } = require('child_process');
const fs = require('fs');
const path = require('path');
Expand All @@ -17,9 +18,8 @@ export async function installFabric(ref: Ref) {
const startTime = Date.now();

const { launcher, map } = storeToRefs(useSourcesStore());
const { homeDir, minecraftDir, drehmalDir, memory } = storeToRefs(
useInstallerStore()
);
const { homeDir, minecraftDir, drehmalDir, memory, javaExePath } =
storeToRefs(useInstallerStore());
const { processingFabric } = storeToRefs(useStateStore());

const fabricPath = path.join(
Expand All @@ -30,15 +30,18 @@ export async function installFabric(ref: Ref) {

console.log(`Downloading Fabric installer to "${fabricPath}"`);

ref.value.label = 'Downloading Fabric installer';
ref.value.label = 'Downloading Java runtime';
await getJre();
ref.value.progress = 0.25;
ref.value.percent = 25;

ref.value.label = 'Downloading Fabric installer';
downloadFile(launcher.value.fabric.source, fabricPath).then(() => {
ref.value.label = 'Installing Fabric';
ref.value.progress = 0.5;
ref.value.percent = 50;
console.log('Calling Fabric installer');
const fabricProc = spawn('java', [
const fabricProc = spawn(javaExePath.value, [
'-jar',
fabricPath,
'client',
Expand All @@ -54,7 +57,7 @@ export async function installFabric(ref: Ref) {
console.error(`Fabric: ${data}`);
});

fabricProc.on('close', (code: any) => {
fabricProc.on('close', async (code: any) => {
const taken = ((Date.now() - startTime) / 1000).toFixed(2);

console.log(`Fabric process exited with code ${code} (${taken}s total)`);
Expand Down Expand Up @@ -86,12 +89,17 @@ export async function installFabric(ref: Ref) {
data['profiles'][map.value.versionName][
'javaArgs'
] = `-Xmx${memoryInMb}M`;
// ['javaArgs'] = `-Xmx${memoryInMb}M -Xms${memoryInMb}M -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions -XX:+AlwaysActAsServerClassMachine -XX:+AlwaysPreTouch -XX:+DisableExplicitGC -XX:+UseNUMA -XX:NmethodSweepActivity=1 -XX:ReservedCodeCacheSize=400M -XX:NonNMethodCodeHeapSize=12M -XX:ProfiledCodeHeapSize=194M -XX:NonProfiledCodeHeapSize=194M -XX:-DontCompileHugeMethods -XX:MaxNodeLimit=240000 -XX:NodeLimitFudgeFactor=8000 -XX:+UseVectorCmov -XX:+PerfDisableSharedMem -XX:+UseFastUnorderedTimeStamps -XX:+UseCriticalJavaThreadPriority -XX:ThreadPriorityPolicy=1 -XX:AllocatePrefetchStyle=3 -XX:+UseG1GC -XX:MaxGCPauseMillis=130 -XX:+UnlockExperimentalVMOptions -XX:+DisableExplicitGC -XX:+AlwaysPreTouch -XX:G1NewSizePercent=28 -XX:G1HeapRegionSize=16M -XX:G1ReservePercent=20 -XX:G1MixedGCCountTarget=3 -XX:InitiatingHeapOccupancyPercent=10 -XX:G1MixedGCLiveThresholdPercent=90 -XX:G1RSetUpdatingPauseTimePercent=0 -XX:SurvivorRatio=32 -XX:MaxTenuringThreshold=1 -XX:G1SATBBufferEnqueueingThresholdPercent=30 -XX:G1ConcMarkStepDurationMillis=5 -XX:G1ConcRSHotCardLimit=16 -XX:G1ConcRefinementServiceIntervalMillis=150`;
const currDateISO = dayjs.utc().toISOString();
data['profiles'][map.value.versionName]['lastUsed'] = currDateISO;
data['profiles'][map.value.versionName]['created'] = currDateISO;

data['profiles'][map.value.versionName]['gameDir'] = drehmalDir.value;

const javawPath = await getJre();
if (javawPath)
data['profiles'][map.value.versionName]['javaDir'] = javaExePath.value;

fs.writeFileSync(profileFilePath, JSON.stringify(data), 'utf-8');

ref.value.label = 'Minecraft profile created!';
Expand Down
Loading

0 comments on commit 3495f89

Please sign in to comment.