@dimzxzzx07/mc-headless 1.6.0 → 1.8.0
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 +316 -390
- package/dist/core/JavaChecker.d.ts +2 -2
- package/dist/core/JavaChecker.d.ts.map +1 -1
- package/dist/core/JavaChecker.js +63 -21
- package/dist/core/JavaChecker.js.map +1 -1
- package/dist/core/MinecraftServer.d.ts +46 -0
- package/dist/core/MinecraftServer.d.ts.map +1 -1
- package/dist/core/MinecraftServer.js +599 -7
- package/dist/core/MinecraftServer.js.map +1 -1
- package/dist/platforms/ViaVersion.d.ts +7 -4
- package/dist/platforms/ViaVersion.d.ts.map +1 -1
- package/dist/platforms/ViaVersion.js +108 -124
- package/dist/platforms/ViaVersion.js.map +1 -1
- package/package.json +1 -1
- package/src/core/JavaChecker.ts +59 -24
- package/src/core/MinecraftServer.ts +685 -8
- package/src/platforms/ViaVersion.ts +119 -134
- package/src/scripts/install-java.sh +97 -32
|
@@ -3,192 +3,179 @@ import { FileUtils } from '../utils/FileUtils';
|
|
|
3
3
|
import { Logger } from '../utils/Logger';
|
|
4
4
|
import * as path from 'path';
|
|
5
5
|
import axios from 'axios';
|
|
6
|
+
import * as fs from 'fs-extra';
|
|
6
7
|
|
|
7
8
|
export interface ViaVersionInfo {
|
|
8
9
|
version: string;
|
|
9
|
-
build: number;
|
|
10
10
|
downloadUrl: string;
|
|
11
|
+
fileName: string;
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
export class ViaVersionManager {
|
|
14
15
|
private logger = Logger.getInstance();
|
|
15
16
|
|
|
17
|
+
private readonly VIAVERSION_URL = 'https://github.com/ViaVersion/ViaVersion/releases/download/5.7.2/ViaVersion-5.7.2.jar';
|
|
18
|
+
private readonly VIABACKWARDS_URL = 'https://github.com/ViaVersion/ViaBackwards/releases/download/5.7.2/ViaBackwards-5.7.2.jar';
|
|
19
|
+
private readonly VIAREWIND_URL = 'https://github.com/ViaVersion/ViaRewind/releases/download/4.0.15/ViaRewind-4.0.15.jar';
|
|
20
|
+
|
|
16
21
|
public async setup(config: MinecraftConfig): Promise<void> {
|
|
17
22
|
const pluginsDir = config.folders.plugins;
|
|
18
23
|
await FileUtils.ensureDir(pluginsDir);
|
|
19
24
|
|
|
20
25
|
this.logger.info('Setting up ViaVersion, ViaBackwards, ViaRewind...');
|
|
21
26
|
|
|
27
|
+
await this.cleanupCorruptFiles(pluginsDir);
|
|
28
|
+
|
|
22
29
|
await this.downloadViaVersion(pluginsDir);
|
|
23
30
|
await this.downloadViaBackwards(pluginsDir);
|
|
24
31
|
await this.downloadViaRewind(pluginsDir);
|
|
25
32
|
|
|
33
|
+
await this.verifyAllPlugins(pluginsDir);
|
|
34
|
+
|
|
26
35
|
this.logger.success('ViaVersion suite installed successfully');
|
|
27
36
|
this.logger.info('Players from older versions can now connect to your server');
|
|
28
37
|
}
|
|
29
38
|
|
|
30
|
-
private async
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
return {
|
|
37
|
-
version: version,
|
|
38
|
-
build: 0,
|
|
39
|
-
downloadUrl: response.data.assets[0].browser_download_url
|
|
40
|
-
};
|
|
41
|
-
} catch (error) {
|
|
42
|
-
this.logger.error('Failed to get ViaVersion info from GitHub, using fallback URL');
|
|
43
|
-
return {
|
|
44
|
-
version: '4.9.0',
|
|
45
|
-
build: 0,
|
|
46
|
-
downloadUrl: 'https://github.com/ViaVersion/ViaVersion/releases/download/v4.9.0/ViaVersion-4.9.0.jar'
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
}
|
|
39
|
+
private async cleanupCorruptFiles(pluginsDir: string): Promise<void> {
|
|
40
|
+
const files = [
|
|
41
|
+
{ name: 'ViaVersion.jar', url: this.VIAVERSION_URL },
|
|
42
|
+
{ name: 'ViaBackwards.jar', url: this.VIABACKWARDS_URL },
|
|
43
|
+
{ name: 'ViaRewind.jar', url: this.VIAREWIND_URL }
|
|
44
|
+
];
|
|
50
45
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
const response = await axios.get('https://api.github.com/repos/ViaVersion/ViaBackwards/releases/latest');
|
|
54
|
-
const tag = response.data.tag_name;
|
|
55
|
-
const version = tag.replace('v', '');
|
|
46
|
+
for (const file of files) {
|
|
47
|
+
const filePath = path.join(pluginsDir, file.name);
|
|
56
48
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
49
|
+
if (await FileUtils.fileExists(filePath)) {
|
|
50
|
+
try {
|
|
51
|
+
const stats = await fs.stat(filePath);
|
|
52
|
+
if (stats.size < 100000) {
|
|
53
|
+
this.logger.warning(`Corrupt ${file.name} detected (${stats.size} bytes), removing...`);
|
|
54
|
+
await fs.remove(filePath);
|
|
55
|
+
} else {
|
|
56
|
+
const buffer = await fs.readFile(filePath);
|
|
57
|
+
if (buffer[0] !== 0x50 || buffer[1] !== 0x4B) {
|
|
58
|
+
this.logger.warning(`Invalid ZIP header in ${file.name}, removing...`);
|
|
59
|
+
await fs.remove(filePath);
|
|
60
|
+
} else {
|
|
61
|
+
this.logger.info(`${file.name} is valid, keeping it`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
} catch (error) {
|
|
65
|
+
this.logger.warning(`Error checking ${file.name}, removing...`);
|
|
66
|
+
await fs.remove(filePath);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
private async
|
|
73
|
-
|
|
74
|
-
const response = await axios.get('https://api.github.com/repos/ViaVersion/ViaRewind/releases/latest');
|
|
75
|
-
const tag = response.data.tag_name;
|
|
76
|
-
const version = tag.replace('v', '');
|
|
77
|
-
|
|
78
|
-
return {
|
|
79
|
-
version: version,
|
|
80
|
-
build: 0,
|
|
81
|
-
downloadUrl: response.data.assets[0].browser_download_url
|
|
82
|
-
};
|
|
83
|
-
} catch (error) {
|
|
84
|
-
this.logger.error('Failed to get ViaRewind info from GitHub, using fallback URL');
|
|
85
|
-
return {
|
|
86
|
-
version: '3.0.0',
|
|
87
|
-
build: 0,
|
|
88
|
-
downloadUrl: 'https://github.com/ViaVersion/ViaRewind/releases/download/v3.0.0/ViaRewind-3.0.0.jar'
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
}
|
|
72
|
+
private async downloadFile(url: string, destPath: string, fileName: string): Promise<void> {
|
|
73
|
+
this.logger.info(`Downloading ${fileName}...`);
|
|
92
74
|
|
|
93
|
-
private async downloadViaVersion(pluginsDir: string): Promise<void> {
|
|
94
|
-
const viaVersionJar = path.join(pluginsDir, 'ViaVersion.jar');
|
|
95
|
-
|
|
96
|
-
if (await FileUtils.fileExists(viaVersionJar)) {
|
|
97
|
-
this.logger.info('ViaVersion already exists, skipping download');
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
this.logger.info('Downloading ViaVersion...');
|
|
102
|
-
|
|
103
75
|
try {
|
|
104
|
-
const info = await this.getLatestViaVersionInfo();
|
|
105
|
-
|
|
106
76
|
const response = await axios({
|
|
107
77
|
method: 'GET',
|
|
108
|
-
url:
|
|
109
|
-
responseType: 'stream'
|
|
78
|
+
url: url,
|
|
79
|
+
responseType: 'stream',
|
|
80
|
+
timeout: 60000,
|
|
81
|
+
headers: {
|
|
82
|
+
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
|
|
83
|
+
}
|
|
110
84
|
});
|
|
111
85
|
|
|
112
|
-
const writer =
|
|
86
|
+
const writer = fs.createWriteStream(destPath);
|
|
113
87
|
response.data.pipe(writer);
|
|
114
88
|
|
|
115
|
-
await new Promise((resolve, reject) => {
|
|
116
|
-
writer.on('finish', resolve);
|
|
117
|
-
writer.on('error', reject);
|
|
89
|
+
await new Promise<void>((resolve, reject) => {
|
|
90
|
+
writer.on('finish', () => resolve());
|
|
91
|
+
writer.on('error', (err) => reject(err));
|
|
118
92
|
});
|
|
119
93
|
|
|
120
|
-
|
|
94
|
+
const stats = await fs.stat(destPath);
|
|
95
|
+
if (stats.size < 100000) {
|
|
96
|
+
throw new Error(`Downloaded file too small: ${stats.size} bytes`);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const buffer = await fs.readFile(destPath);
|
|
100
|
+
if (buffer[0] !== 0x50 || buffer[1] !== 0x4B) {
|
|
101
|
+
throw new Error('Invalid ZIP header');
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
this.logger.success(`Downloaded: ${fileName} (${(stats.size / 1024 / 1024).toFixed(2)} MB)`);
|
|
105
|
+
|
|
121
106
|
} catch (error) {
|
|
122
|
-
this.logger.error(
|
|
107
|
+
this.logger.error(`Failed to download ${fileName}:`, error);
|
|
123
108
|
throw error;
|
|
124
109
|
}
|
|
125
110
|
}
|
|
126
111
|
|
|
127
|
-
private async
|
|
128
|
-
const
|
|
112
|
+
private async downloadViaVersion(pluginsDir: string): Promise<void> {
|
|
113
|
+
const destPath = path.join(pluginsDir, 'ViaVersion.jar');
|
|
129
114
|
|
|
130
|
-
if (await FileUtils.fileExists(
|
|
131
|
-
|
|
132
|
-
return;
|
|
115
|
+
if (await FileUtils.fileExists(destPath)) {
|
|
116
|
+
await fs.remove(destPath);
|
|
133
117
|
}
|
|
134
118
|
|
|
135
|
-
this.
|
|
136
|
-
|
|
137
|
-
try {
|
|
138
|
-
const info = await this.getLatestViaBackwardsInfo();
|
|
139
|
-
|
|
140
|
-
const response = await axios({
|
|
141
|
-
method: 'GET',
|
|
142
|
-
url: info.downloadUrl,
|
|
143
|
-
responseType: 'stream'
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
const writer = require('fs').createWriteStream(viaBackwardsJar);
|
|
147
|
-
response.data.pipe(writer);
|
|
148
|
-
|
|
149
|
-
await new Promise((resolve, reject) => {
|
|
150
|
-
writer.on('finish', resolve);
|
|
151
|
-
writer.on('error', reject);
|
|
152
|
-
});
|
|
119
|
+
await this.downloadFile(this.VIAVERSION_URL, destPath, 'ViaVersion.jar');
|
|
120
|
+
}
|
|
153
121
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
122
|
+
private async downloadViaBackwards(pluginsDir: string): Promise<void> {
|
|
123
|
+
const destPath = path.join(pluginsDir, 'ViaBackwards.jar');
|
|
124
|
+
|
|
125
|
+
if (await FileUtils.fileExists(destPath)) {
|
|
126
|
+
await fs.remove(destPath);
|
|
158
127
|
}
|
|
128
|
+
|
|
129
|
+
await this.downloadFile(this.VIABACKWARDS_URL, destPath, 'ViaBackwards.jar');
|
|
159
130
|
}
|
|
160
131
|
|
|
161
132
|
private async downloadViaRewind(pluginsDir: string): Promise<void> {
|
|
162
|
-
const
|
|
133
|
+
const destPath = path.join(pluginsDir, 'ViaRewind.jar');
|
|
163
134
|
|
|
164
|
-
if (await FileUtils.fileExists(
|
|
165
|
-
|
|
166
|
-
return;
|
|
135
|
+
if (await FileUtils.fileExists(destPath)) {
|
|
136
|
+
await fs.remove(destPath);
|
|
167
137
|
}
|
|
168
138
|
|
|
169
|
-
this.
|
|
170
|
-
|
|
171
|
-
try {
|
|
172
|
-
const info = await this.getLatestViaRewindInfo();
|
|
173
|
-
|
|
174
|
-
const response = await axios({
|
|
175
|
-
method: 'GET',
|
|
176
|
-
url: info.downloadUrl,
|
|
177
|
-
responseType: 'stream'
|
|
178
|
-
});
|
|
139
|
+
await this.downloadFile(this.VIAREWIND_URL, destPath, 'ViaRewind.jar');
|
|
140
|
+
}
|
|
179
141
|
|
|
180
|
-
|
|
181
|
-
|
|
142
|
+
private async verifyAllPlugins(pluginsDir: string): Promise<void> {
|
|
143
|
+
const files = ['ViaVersion.jar', 'ViaBackwards.jar', 'ViaRewind.jar'];
|
|
144
|
+
let allValid = true;
|
|
182
145
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
146
|
+
for (const file of files) {
|
|
147
|
+
const filePath = path.join(pluginsDir, file);
|
|
148
|
+
|
|
149
|
+
if (!await FileUtils.fileExists(filePath)) {
|
|
150
|
+
this.logger.error(`${file} is missing!`);
|
|
151
|
+
allValid = false;
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
try {
|
|
156
|
+
const stats = await fs.stat(filePath);
|
|
157
|
+
if (stats.size < 100000) {
|
|
158
|
+
this.logger.error(`${file} is too small: ${stats.size} bytes`);
|
|
159
|
+
allValid = false;
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const buffer = await fs.readFile(filePath);
|
|
164
|
+
if (buffer[0] !== 0x50 || buffer[1] !== 0x4B) {
|
|
165
|
+
this.logger.error(`${file} has invalid ZIP header`);
|
|
166
|
+
allValid = false;
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
this.logger.debug(`${file} verified OK (${(stats.size / 1024 / 1024).toFixed(2)} MB)`);
|
|
171
|
+
} catch (error) {
|
|
172
|
+
this.logger.error(`Failed to verify ${file}:`, error);
|
|
173
|
+
allValid = false;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
187
176
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
this.logger.error('Failed to download ViaRewind', error);
|
|
191
|
-
throw error;
|
|
177
|
+
if (!allValid) {
|
|
178
|
+
throw new Error('Some ViaVersion plugins are corrupt or missing');
|
|
192
179
|
}
|
|
193
180
|
}
|
|
194
181
|
|
|
@@ -202,25 +189,23 @@ export class ViaVersionManager {
|
|
|
202
189
|
const configContent = `# ViaVersion Configuration
|
|
203
190
|
# Auto-generated by mc-headless
|
|
204
191
|
|
|
205
|
-
# Allow older clients to connect
|
|
206
192
|
enable-client-side-block-updates: true
|
|
207
193
|
prevent-collision: true
|
|
208
194
|
auto-team: true
|
|
209
195
|
suppress-metadata-errors: false
|
|
210
196
|
enable-legacy-server-ping: true
|
|
211
197
|
block-connection-method: true
|
|
212
|
-
|
|
213
|
-
# Protocol support
|
|
214
198
|
nms-player-ticking: true
|
|
215
199
|
debug: false
|
|
216
200
|
max-pps: 800
|
|
217
201
|
max-pp-interval: 4
|
|
218
|
-
|
|
219
|
-
# Version-specific fixes
|
|
220
202
|
fix-self-rendering: true
|
|
221
203
|
fix-low-level-collision: true
|
|
222
204
|
shield-blocking: true
|
|
223
205
|
fix-infested-block-breaking: true
|
|
206
|
+
ignore-long-1_16-channel: true
|
|
207
|
+
force-json-transform: false
|
|
208
|
+
use-natives: true
|
|
224
209
|
`;
|
|
225
210
|
|
|
226
211
|
await FileUtils.writeFile(configFile, configContent);
|
|
@@ -1,38 +1,103 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
2
|
|
|
3
|
-
echo "
|
|
3
|
+
echo "Minecraft Headless - Java Auto Installer"
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
JAVA_VERSION=${1:-17}
|
|
6
|
+
echo "Target Java version: $JAVA_VERSION"
|
|
7
|
+
|
|
8
|
+
detect_os() {
|
|
9
|
+
if [ -f /etc/os-release ]; then
|
|
10
|
+
. /etc/os-release
|
|
11
|
+
echo "$ID"
|
|
12
|
+
elif [ -n "$TERMUX_VERSION" ]; then
|
|
13
|
+
echo "termux"
|
|
14
|
+
elif [ "$(uname)" == "Darwin" ]; then
|
|
15
|
+
echo "macos"
|
|
16
|
+
elif [ "$(expr substr $(uname -s) 1 5)" == "MINGW" ]; then
|
|
17
|
+
echo "windows"
|
|
18
|
+
else
|
|
19
|
+
echo "unknown"
|
|
20
|
+
fi
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
OS=$(detect_os)
|
|
24
|
+
echo "Detected OS: $OS"
|
|
25
|
+
|
|
26
|
+
install_java_17() {
|
|
27
|
+
case $OS in
|
|
28
|
+
ubuntu|debian)
|
|
29
|
+
apt update
|
|
30
|
+
apt install -y openjdk-17-jre-headless
|
|
31
|
+
;;
|
|
32
|
+
centos|rhel|fedora)
|
|
33
|
+
if command -v dnf &> /dev/null; then
|
|
34
|
+
dnf install -y java-17-openjdk-headless
|
|
35
|
+
else
|
|
36
|
+
yum install -y java-17-openjdk-headless
|
|
37
|
+
fi
|
|
38
|
+
;;
|
|
39
|
+
arch)
|
|
40
|
+
pacman -S --noconfirm jre17-openjdk-headless
|
|
41
|
+
;;
|
|
42
|
+
termux)
|
|
43
|
+
pkg install -y openjdk-17
|
|
44
|
+
;;
|
|
45
|
+
macos)
|
|
46
|
+
if ! command -v brew &> /dev/null; then
|
|
47
|
+
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
|
48
|
+
fi
|
|
49
|
+
brew install openjdk@17
|
|
50
|
+
;;
|
|
51
|
+
*)
|
|
52
|
+
echo "Unsupported OS for Java 17 installation"
|
|
53
|
+
return 1
|
|
54
|
+
;;
|
|
55
|
+
esac
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
install_java_21() {
|
|
59
|
+
case $OS in
|
|
60
|
+
ubuntu|debian)
|
|
61
|
+
apt update
|
|
62
|
+
apt install -y openjdk-21-jre-headless
|
|
63
|
+
;;
|
|
64
|
+
centos|rhel|fedora)
|
|
65
|
+
if command -v dnf &> /dev/null; then
|
|
66
|
+
dnf install -y java-21-openjdk-headless
|
|
67
|
+
else
|
|
68
|
+
yum install -y java-21-openjdk-headless
|
|
69
|
+
fi
|
|
70
|
+
;;
|
|
71
|
+
arch)
|
|
72
|
+
pacman -S --noconfirm jre21-openjdk-headless
|
|
73
|
+
;;
|
|
74
|
+
termux)
|
|
75
|
+
echo "Java 21 not available in Termux, installing Java 17 instead"
|
|
76
|
+
install_java_17
|
|
77
|
+
;;
|
|
78
|
+
macos)
|
|
79
|
+
if ! command -v brew &> /dev/null; then
|
|
80
|
+
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
|
81
|
+
fi
|
|
82
|
+
brew install openjdk@21
|
|
83
|
+
;;
|
|
84
|
+
*)
|
|
85
|
+
echo "Unsupported OS for Java 21 installation"
|
|
86
|
+
return 1
|
|
87
|
+
;;
|
|
88
|
+
esac
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if [ "$JAVA_VERSION" = "21" ]; then
|
|
92
|
+
install_java_21
|
|
10
93
|
else
|
|
11
|
-
|
|
94
|
+
install_java_17
|
|
12
95
|
fi
|
|
13
96
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
;;
|
|
22
|
-
fedora)
|
|
23
|
-
dnf install -y java-17-openjdk-headless
|
|
24
|
-
;;
|
|
25
|
-
arch)
|
|
26
|
-
pacman -S --noconfirm jre17-openjdk-headless
|
|
27
|
-
;;
|
|
28
|
-
termux)
|
|
29
|
-
pkg install -y openjdk-17
|
|
30
|
-
;;
|
|
31
|
-
*)
|
|
32
|
-
echo "Unsupported OS. Please install Java 17 manually."
|
|
33
|
-
exit 1
|
|
34
|
-
;;
|
|
35
|
-
esac
|
|
36
|
-
|
|
37
|
-
echo "Java installation completed."
|
|
38
|
-
java -version
|
|
97
|
+
if [ $? -eq 0 ]; then
|
|
98
|
+
echo "Java installation completed."
|
|
99
|
+
java -version
|
|
100
|
+
else
|
|
101
|
+
echo "Java installation failed."
|
|
102
|
+
exit 1
|
|
103
|
+
fi
|