@dimzxzzx07/mc-headless 2.2.1 → 2.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +658 -765
- package/dist/core/JavaChecker.d.ts +8 -2
- package/dist/core/JavaChecker.d.ts.map +1 -1
- package/dist/core/JavaChecker.js +219 -104
- package/dist/core/JavaChecker.js.map +1 -1
- package/dist/core/MinecraftServer.d.ts +17 -32
- package/dist/core/MinecraftServer.d.ts.map +1 -1
- package/dist/core/MinecraftServer.js +449 -186
- package/dist/core/MinecraftServer.js.map +1 -1
- package/dist/index.d.ts +19 -18
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +40 -18
- package/dist/index.js.map +1 -1
- package/dist/platforms/GeyserBridge.d.ts +21 -3
- package/dist/platforms/GeyserBridge.d.ts.map +1 -1
- package/dist/platforms/GeyserBridge.js +160 -60
- package/dist/platforms/GeyserBridge.js.map +1 -1
- package/dist/platforms/PluginManager.d.ts +16 -0
- package/dist/platforms/PluginManager.d.ts.map +1 -0
- package/dist/platforms/PluginManager.js +208 -0
- package/dist/platforms/PluginManager.js.map +1 -0
- package/dist/platforms/ViaVersion.d.ts +1 -7
- package/dist/platforms/ViaVersion.d.ts.map +1 -1
- package/dist/platforms/ViaVersion.js +23 -87
- package/dist/platforms/ViaVersion.js.map +1 -1
- package/dist/types/index.d.ts +189 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +4 -2
- package/src/core/JavaChecker.ts +224 -108
- package/src/core/MinecraftServer.ts +540 -254
- package/src/index.ts +19 -19
- package/src/platforms/GeyserBridge.ts +196 -80
- package/src/platforms/PluginManager.ts +206 -0
- package/src/platforms/ViaVersion.ts +26 -107
- package/src/types/index.ts +206 -0
package/src/core/JavaChecker.ts
CHANGED
|
@@ -3,8 +3,8 @@ import * as fs from 'fs-extra';
|
|
|
3
3
|
import * as path from 'path';
|
|
4
4
|
import * as https from 'https';
|
|
5
5
|
import * as http from 'http';
|
|
6
|
+
import * as os from 'os';
|
|
6
7
|
import * as tar from 'tar';
|
|
7
|
-
import { Logger } from '../utils/Logger';
|
|
8
8
|
|
|
9
9
|
export interface JavaInfo {
|
|
10
10
|
path: string;
|
|
@@ -13,21 +13,67 @@ export interface JavaInfo {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
export class JavaChecker {
|
|
16
|
-
private static
|
|
17
|
-
private static readonly JAVA_DIR = path.join(process.cwd(), '.java');
|
|
16
|
+
private static readonly JAVA_DIR = JavaChecker.getOptimalJavaDirectory();
|
|
18
17
|
|
|
19
|
-
// Hanya pakai URL yang reliable dan direct download
|
|
20
18
|
private static readonly JAVA_URLS = {
|
|
21
|
-
'21':
|
|
22
|
-
'
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
'
|
|
28
|
-
|
|
19
|
+
'21': {
|
|
20
|
+
'x64': [
|
|
21
|
+
'https://github.com/adoptium/temurin21-binaries/releases/download/jdk-21.0.2%2B13/OpenJDK21U-jre_x64_linux_hotspot_21.0.2_13.tar.gz',
|
|
22
|
+
'https://corretto.aws/downloads/latest/amazon-corretto-21-x64-linux-jre.tar.gz',
|
|
23
|
+
'https://download.bell-sw.com/java/21.0.2+13/bellsoft-jre21.0.2+13-linux-amd64.tar.gz'
|
|
24
|
+
],
|
|
25
|
+
'arm64': [
|
|
26
|
+
'https://github.com/adoptium/temurin21-binaries/releases/download/jdk-21.0.2%2B13/OpenJDK21U-jre_aarch64_linux_hotspot_21.0.2_13.tar.gz',
|
|
27
|
+
'https://corretto.aws/downloads/latest/amazon-corretto-21-aarch64-linux-jre.tar.gz',
|
|
28
|
+
'https://download.bell-sw.com/java/21.0.2+13/bellsoft-jre21.0.2+13-linux-aarch64.tar.gz'
|
|
29
|
+
],
|
|
30
|
+
'arm': [
|
|
31
|
+
'https://github.com/adoptium/temurin21-binaries/releases/download/jdk-21.0.2%2B13/OpenJDK21U-jre_arm_linux_hotspot_21.0.2_13.tar.gz'
|
|
32
|
+
]
|
|
33
|
+
},
|
|
34
|
+
'17': {
|
|
35
|
+
'x64': [
|
|
36
|
+
'https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.10%2B7/OpenJDK17U-jre_x64_linux_hotspot_17.0.10_7.tar.gz',
|
|
37
|
+
'https://corretto.aws/downloads/latest/amazon-corretto-17-x64-linux-jre.tar.gz',
|
|
38
|
+
'https://download.bell-sw.com/java/17.0.10+13/bellsoft-jre17.0.10+13-linux-amd64.tar.gz'
|
|
39
|
+
],
|
|
40
|
+
'arm64': [
|
|
41
|
+
'https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.10%2B7/OpenJDK17U-jre_aarch64_linux_hotspot_17.0.10_7.tar.gz',
|
|
42
|
+
'https://corretto.aws/downloads/latest/amazon-corretto-17-aarch64-linux-jre.tar.gz',
|
|
43
|
+
'https://download.bell-sw.com/java/17.0.10+13/bellsoft-jre17.0.10+13-linux-aarch64.tar.gz'
|
|
44
|
+
],
|
|
45
|
+
'arm': [
|
|
46
|
+
'https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.10%2B7/OpenJDK17U-jre_arm_linux_hotspot_17.0.10_7.tar.gz'
|
|
47
|
+
]
|
|
48
|
+
}
|
|
29
49
|
};
|
|
30
50
|
|
|
51
|
+
private static getOptimalJavaDirectory(): string {
|
|
52
|
+
const pterodactylDir = '/home/container/.java';
|
|
53
|
+
const tmpDir = '/tmp/.mc-headless';
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
if (fs.existsSync('/home/container')) {
|
|
57
|
+
return pterodactylDir;
|
|
58
|
+
}
|
|
59
|
+
} catch {
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const totalRamGB = os.totalmem() / 1024 / 1024 / 1024;
|
|
63
|
+
if (totalRamGB < 3) {
|
|
64
|
+
console.warn(`Warning: Low RAM (${totalRamGB.toFixed(1)} GB). Java in /tmp may cause issues.`);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return tmpDir;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
private static getArch(): 'x64' | 'arm64' | 'arm' {
|
|
71
|
+
const arch = process.arch;
|
|
72
|
+
if (arch === 'arm64') return 'arm64';
|
|
73
|
+
if (arch === 'arm') return 'arm';
|
|
74
|
+
return 'x64';
|
|
75
|
+
}
|
|
76
|
+
|
|
31
77
|
public static getRequiredJavaVersion(serverVersion: string): '17' | '21' {
|
|
32
78
|
if (serverVersion.startsWith('1.21') || serverVersion === '1.21.11') {
|
|
33
79
|
return '21';
|
|
@@ -42,11 +88,8 @@ export class JavaChecker {
|
|
|
42
88
|
return new Promise((resolve) => {
|
|
43
89
|
exec('which java', (error, stdout) => {
|
|
44
90
|
if (error || !stdout.trim()) {
|
|
45
|
-
this.logger.warning('Java is not installed in system');
|
|
46
91
|
resolve(false);
|
|
47
92
|
} else {
|
|
48
|
-
const javaPath = stdout.trim();
|
|
49
|
-
this.logger.success(`System Java found at: ${javaPath}`);
|
|
50
93
|
resolve(true);
|
|
51
94
|
}
|
|
52
95
|
});
|
|
@@ -65,95 +108,166 @@ export class JavaChecker {
|
|
|
65
108
|
public static getSystemJavaVersion(): string | null {
|
|
66
109
|
try {
|
|
67
110
|
const output = execSync('java -version 2>&1').toString();
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
111
|
+
|
|
112
|
+
const versionRegex = /(?:version|openjdk|java)[\s"]+(\d+)(?:\.(\d+))?/i;
|
|
113
|
+
const match = output.match(versionRegex);
|
|
114
|
+
|
|
115
|
+
if (match) {
|
|
116
|
+
const majorVersion = parseInt(match[1]);
|
|
117
|
+
if (majorVersion === 21) return '21';
|
|
118
|
+
if (majorVersion === 17) return '17';
|
|
119
|
+
if (majorVersion === 11) return '11';
|
|
120
|
+
if (majorVersion === 8) return '8';
|
|
121
|
+
if (majorVersion === 1 && match[2] === '8') return '8';
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (output.includes('version "21') || output.includes('openjdk 21')) return '21';
|
|
125
|
+
if (output.includes('version "17') || output.includes('openjdk 17')) return '17';
|
|
126
|
+
if (output.includes('version "11') || output.includes('openjdk 11')) return '11';
|
|
127
|
+
if (output.includes('version "1.8') || output.includes('openjdk 1.8')) return '8';
|
|
128
|
+
|
|
129
|
+
return null;
|
|
74
130
|
} catch {
|
|
75
131
|
return null;
|
|
76
132
|
}
|
|
77
133
|
}
|
|
78
134
|
|
|
79
|
-
private static
|
|
135
|
+
private static shouldUpdateJava(javaHome: string): boolean {
|
|
136
|
+
try {
|
|
137
|
+
const stats = fs.statSync(javaHome);
|
|
138
|
+
const ageInDays = (Date.now() - stats.mtimeMs) / (1000 * 60 * 60 * 24);
|
|
139
|
+
return ageInDays > 30;
|
|
140
|
+
} catch {
|
|
141
|
+
return true;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
private static async downloadAndExtractWithStream(url: string, javaHome: string, retryCount = 0): Promise<void> {
|
|
146
|
+
const maxRetries = 3;
|
|
147
|
+
const userAgents = [
|
|
148
|
+
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36',
|
|
149
|
+
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36',
|
|
150
|
+
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36'
|
|
151
|
+
];
|
|
152
|
+
|
|
80
153
|
return new Promise((resolve, reject) => {
|
|
81
|
-
|
|
154
|
+
console.log(`Downloading Java...`);
|
|
82
155
|
|
|
83
156
|
const protocol = url.startsWith('https') ? https : http;
|
|
84
157
|
|
|
158
|
+
let isDone = false;
|
|
159
|
+
let cleanup = () => {
|
|
160
|
+
if (!isDone) {
|
|
161
|
+
isDone = true;
|
|
162
|
+
fs.remove(javaHome).catch(() => {});
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
|
|
85
166
|
const request = protocol.get(url, {
|
|
86
167
|
headers: {
|
|
87
|
-
'User-Agent':
|
|
168
|
+
'User-Agent': userAgents[retryCount % userAgents.length],
|
|
169
|
+
'Accept': 'application/octet-stream',
|
|
170
|
+
'Accept-Encoding': 'gzip, deflate'
|
|
88
171
|
}
|
|
89
172
|
}, (response) => {
|
|
90
173
|
if (response.statusCode === 301 || response.statusCode === 302 || response.statusCode === 307 || response.statusCode === 308) {
|
|
91
174
|
const location = response.headers.location;
|
|
92
|
-
if (location) {
|
|
93
|
-
this.
|
|
94
|
-
|
|
95
|
-
|
|
175
|
+
if (location && retryCount < maxRetries) {
|
|
176
|
+
this.downloadAndExtractWithStream(location, javaHome, retryCount + 1).then(resolve).catch(reject);
|
|
177
|
+
} else {
|
|
178
|
+
cleanup();
|
|
179
|
+
reject(new Error('Redirect failed'));
|
|
96
180
|
}
|
|
181
|
+
return;
|
|
97
182
|
}
|
|
98
183
|
|
|
99
184
|
if (response.statusCode !== 200) {
|
|
100
|
-
|
|
185
|
+
if (response.statusCode === 429 && retryCount < maxRetries) {
|
|
186
|
+
setTimeout(() => {
|
|
187
|
+
this.downloadAndExtractWithStream(url, javaHome, retryCount + 1).then(resolve).catch(reject);
|
|
188
|
+
}, 10000);
|
|
189
|
+
} else if (response.statusCode && response.statusCode >= 500 && retryCount < maxRetries) {
|
|
190
|
+
setTimeout(() => {
|
|
191
|
+
this.downloadAndExtractWithStream(url, javaHome, retryCount + 1).then(resolve).catch(reject);
|
|
192
|
+
}, 10000);
|
|
193
|
+
} else {
|
|
194
|
+
cleanup();
|
|
195
|
+
reject(new Error(`Download failed: ${response.statusCode}`));
|
|
196
|
+
}
|
|
101
197
|
return;
|
|
102
198
|
}
|
|
103
199
|
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
reject(new Error('Received HTML instead of binary - likely license redirect'));
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
200
|
+
const contentLength = response.headers['content-length'];
|
|
201
|
+
let downloadedBytes = 0;
|
|
109
202
|
|
|
110
|
-
|
|
111
|
-
const totalSize = parseInt(response.headers['content-length'] || '0');
|
|
112
|
-
let downloadedSize = 0;
|
|
113
|
-
let lastPercent = 0;
|
|
203
|
+
fs.ensureDirSync(javaHome);
|
|
114
204
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
const percent = ((downloadedSize / totalSize) * 100).toFixed(1);
|
|
119
|
-
if (parseFloat(percent) >= lastPercent + 5 || parseFloat(percent) >= 100) {
|
|
120
|
-
lastPercent = parseFloat(percent);
|
|
121
|
-
process.stdout.write(`\rDownloading Java: ${percent}% (${(downloadedSize / 1024 / 1024).toFixed(1)} MB)`);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
205
|
+
const extractor = tar.extract({
|
|
206
|
+
cwd: javaHome,
|
|
207
|
+
strip: 1
|
|
124
208
|
});
|
|
125
209
|
|
|
126
|
-
|
|
210
|
+
let extractError: Error | null = null;
|
|
127
211
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
const stats = fs.statSync(destPath);
|
|
133
|
-
if (stats.size < 1000000) {
|
|
134
|
-
fs.unlinkSync(destPath);
|
|
135
|
-
reject(new Error(`Downloaded file too small: ${stats.size} bytes - possibly HTML page`));
|
|
136
|
-
return;
|
|
212
|
+
extractor.on('finish', () => {
|
|
213
|
+
if (!isDone) {
|
|
214
|
+
isDone = true;
|
|
215
|
+
resolve();
|
|
137
216
|
}
|
|
138
|
-
|
|
139
|
-
resolve();
|
|
140
217
|
});
|
|
141
218
|
|
|
142
|
-
|
|
143
|
-
|
|
219
|
+
extractor.on('error', (err) => {
|
|
220
|
+
extractError = err;
|
|
221
|
+
cleanup();
|
|
144
222
|
reject(err);
|
|
145
223
|
});
|
|
224
|
+
|
|
225
|
+
response.on('data', (chunk) => {
|
|
226
|
+
downloadedBytes += chunk.length;
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
response.on('error', (err) => {
|
|
230
|
+
extractor.end();
|
|
231
|
+
cleanup();
|
|
232
|
+
reject(err);
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
response.on('end', () => {
|
|
236
|
+
if (contentLength) {
|
|
237
|
+
const expected = parseInt(contentLength);
|
|
238
|
+
if (downloadedBytes < expected * 0.95) {
|
|
239
|
+
cleanup();
|
|
240
|
+
reject(new Error(`Download incomplete: ${downloadedBytes} of ${expected} bytes`));
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
extractor.on('finish', () => {
|
|
246
|
+
if (!isDone && !extractError) {
|
|
247
|
+
isDone = true;
|
|
248
|
+
resolve();
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
response.pipe(extractor);
|
|
146
254
|
});
|
|
147
255
|
|
|
148
256
|
request.on('error', (err) => {
|
|
149
|
-
|
|
150
|
-
|
|
257
|
+
if (retryCount < maxRetries) {
|
|
258
|
+
setTimeout(() => {
|
|
259
|
+
this.downloadAndExtractWithStream(url, javaHome, retryCount + 1).then(resolve).catch(reject);
|
|
260
|
+
}, 5000);
|
|
261
|
+
} else {
|
|
262
|
+
cleanup();
|
|
263
|
+
reject(err);
|
|
264
|
+
}
|
|
151
265
|
});
|
|
152
266
|
|
|
153
267
|
request.setTimeout(300000, () => {
|
|
154
268
|
request.destroy();
|
|
155
|
-
|
|
156
|
-
reject(new Error('Download timeout
|
|
269
|
+
cleanup();
|
|
270
|
+
reject(new Error('Download timeout'));
|
|
157
271
|
});
|
|
158
272
|
|
|
159
273
|
request.end();
|
|
@@ -163,55 +277,50 @@ export class JavaChecker {
|
|
|
163
277
|
public static async getOrDownloadPortableJava(version: '17' | '21'): Promise<JavaInfo> {
|
|
164
278
|
await fs.ensureDir(this.JAVA_DIR);
|
|
165
279
|
|
|
166
|
-
const
|
|
280
|
+
const arch = this.getArch();
|
|
281
|
+
const javaHome = path.join(this.JAVA_DIR, `jre-${version}-${arch}`);
|
|
167
282
|
const javaBin = path.join(javaHome, 'bin', 'java');
|
|
168
283
|
|
|
169
284
|
if (await fs.pathExists(javaBin)) {
|
|
170
|
-
this.
|
|
171
|
-
|
|
172
|
-
try {
|
|
173
|
-
const versionOutput = execSync(`"${javaBin}" -version 2>&1`).toString();
|
|
174
|
-
this.logger.debug(`Portable Java version: ${versionOutput.split('\n')[0]}`);
|
|
285
|
+
if (!this.shouldUpdateJava(javaHome)) {
|
|
175
286
|
return {
|
|
176
287
|
path: javaBin,
|
|
177
288
|
version: version,
|
|
178
289
|
type: 'portable'
|
|
179
290
|
};
|
|
180
|
-
} catch (error) {
|
|
181
|
-
this.logger.warning(`Existing Java seems corrupted, re-downloading...`);
|
|
182
|
-
await fs.remove(javaHome);
|
|
183
291
|
}
|
|
292
|
+
console.log('Java update available, downloading latest...');
|
|
293
|
+
await fs.remove(javaHome);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
const archUrls = this.JAVA_URLS[version]?.[arch];
|
|
297
|
+
if (!archUrls || archUrls.length === 0) {
|
|
298
|
+
throw new Error(`No Java download for ${version} on ${arch}`);
|
|
184
299
|
}
|
|
185
300
|
|
|
186
|
-
const urls = this.JAVA_URLS[version] || this.JAVA_URLS['21'];
|
|
187
301
|
let lastError: Error | null = null;
|
|
188
302
|
|
|
189
|
-
for (let i = 0; i <
|
|
190
|
-
const url =
|
|
191
|
-
const tarPath = path.join(this.JAVA_DIR, `jre-${version}-${Date.now()}.tar.gz`);
|
|
303
|
+
for (let i = 0; i < archUrls.length; i++) {
|
|
304
|
+
const url = archUrls[i];
|
|
192
305
|
|
|
193
306
|
try {
|
|
194
|
-
|
|
195
|
-
this.logger.info(`URL: ${url}`);
|
|
196
|
-
|
|
197
|
-
await this.downloadWithNode(url, tarPath);
|
|
198
|
-
|
|
199
|
-
this.logger.info(`Extracting Java ${version}...`);
|
|
307
|
+
await fs.remove(javaHome);
|
|
200
308
|
await fs.ensureDir(javaHome);
|
|
201
|
-
await tar.extract({
|
|
202
|
-
file: tarPath,
|
|
203
|
-
cwd: javaHome,
|
|
204
|
-
strip: 1
|
|
205
|
-
});
|
|
206
309
|
|
|
207
|
-
await
|
|
310
|
+
await this.downloadAndExtractWithStream(url, javaHome);
|
|
208
311
|
|
|
209
|
-
await fs.
|
|
312
|
+
if (!await fs.pathExists(javaBin)) {
|
|
313
|
+
throw new Error('Java binary not found after extraction');
|
|
314
|
+
}
|
|
210
315
|
|
|
211
|
-
|
|
316
|
+
await fs.chmod(javaBin, 0o755);
|
|
212
317
|
|
|
213
|
-
|
|
214
|
-
|
|
318
|
+
try {
|
|
319
|
+
execSync(`"${javaBin}" -version 2>&1`);
|
|
320
|
+
} catch {
|
|
321
|
+
await fs.remove(javaHome);
|
|
322
|
+
throw new Error('Java verification failed');
|
|
323
|
+
}
|
|
215
324
|
|
|
216
325
|
return {
|
|
217
326
|
path: javaBin,
|
|
@@ -221,55 +330,62 @@ export class JavaChecker {
|
|
|
221
330
|
|
|
222
331
|
} catch (error) {
|
|
223
332
|
lastError = error instanceof Error ? error : new Error(String(error));
|
|
224
|
-
|
|
225
|
-
await fs.remove(
|
|
333
|
+
console.log(`Download attempt ${i + 1} failed, trying next source...`);
|
|
334
|
+
await fs.remove(javaHome).catch(() => {});
|
|
226
335
|
}
|
|
227
336
|
}
|
|
228
337
|
|
|
229
|
-
throw new Error(`Failed to download Java
|
|
338
|
+
throw new Error(`Failed to download Java: ${lastError?.message}`);
|
|
230
339
|
}
|
|
231
340
|
|
|
232
341
|
public static async ensureJava(serverVersion: string, usePortable: boolean = true): Promise<JavaInfo> {
|
|
233
342
|
const requiredVersion = this.getRequiredJavaVersion(serverVersion);
|
|
234
|
-
this.logger.info(`Server requires Java ${requiredVersion}`);
|
|
235
343
|
|
|
236
344
|
if (!usePortable) {
|
|
237
345
|
const systemJava = this.getSystemJavaPath();
|
|
238
346
|
if (systemJava) {
|
|
239
347
|
const systemVersion = this.getSystemJavaVersion();
|
|
240
348
|
if (systemVersion === requiredVersion) {
|
|
241
|
-
this.logger.success(`Using system Java ${systemVersion} at ${systemJava}`);
|
|
242
349
|
return {
|
|
243
350
|
path: systemJava,
|
|
244
351
|
version: systemVersion,
|
|
245
352
|
type: 'system'
|
|
246
353
|
};
|
|
247
|
-
} else {
|
|
248
|
-
this.logger.warning(`System Java is ${systemVersion}, but server needs Java ${requiredVersion}`);
|
|
249
354
|
}
|
|
250
355
|
}
|
|
251
356
|
}
|
|
252
357
|
|
|
253
|
-
this.logger.info(`Downloading portable Java ${requiredVersion}...`);
|
|
254
358
|
return this.getOrDownloadPortableJava(requiredVersion);
|
|
255
359
|
}
|
|
256
360
|
|
|
257
361
|
public static cleanupOldJava(): void {
|
|
258
362
|
try {
|
|
363
|
+
if (!fs.existsSync(this.JAVA_DIR)) return;
|
|
364
|
+
|
|
259
365
|
const files = fs.readdirSync(this.JAVA_DIR);
|
|
260
366
|
const now = Date.now();
|
|
261
367
|
const oneDay = 24 * 60 * 60 * 1000;
|
|
262
368
|
|
|
263
369
|
files.forEach(file => {
|
|
264
370
|
const filePath = path.join(this.JAVA_DIR, file);
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
371
|
+
try {
|
|
372
|
+
const stats = fs.statSync(filePath);
|
|
373
|
+
if (now - stats.mtimeMs > oneDay) {
|
|
374
|
+
if (stats.isDirectory()) {
|
|
375
|
+
fs.removeSync(filePath);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
} catch {
|
|
269
379
|
}
|
|
270
380
|
});
|
|
271
|
-
} catch
|
|
272
|
-
this.logger.debug('No old Java to cleanup');
|
|
381
|
+
} catch {
|
|
273
382
|
}
|
|
274
383
|
}
|
|
384
|
+
|
|
385
|
+
public static getJavaInfo(): { dir: string; arch: string } {
|
|
386
|
+
return {
|
|
387
|
+
dir: this.JAVA_DIR,
|
|
388
|
+
arch: this.getArch()
|
|
389
|
+
};
|
|
390
|
+
}
|
|
275
391
|
}
|