@dimzxzzx07/mc-headless 2.2.2 → 2.2.4
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 +652 -776
- package/dist/core/MinecraftServer.d.ts +13 -38
- package/dist/core/MinecraftServer.d.ts.map +1 -1
- package/dist/core/MinecraftServer.js +424 -336
- 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/MinecraftServer.ts +503 -414
- 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
|
@@ -4,12 +4,11 @@ import { Logger } from '../utils/Logger';
|
|
|
4
4
|
import * as path from 'path';
|
|
5
5
|
import axios from 'axios';
|
|
6
6
|
import * as fs from 'fs-extra';
|
|
7
|
+
import * as stream from 'stream';
|
|
8
|
+
import * as util from 'util';
|
|
7
9
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
downloadUrl: string;
|
|
11
|
-
fileName: string;
|
|
12
|
-
}
|
|
10
|
+
const pipeline = util.promisify(stream.pipeline);
|
|
11
|
+
const finished = util.promisify(stream.finished);
|
|
13
12
|
|
|
14
13
|
export class ViaVersionManager {
|
|
15
14
|
private logger = Logger.getInstance();
|
|
@@ -24,52 +23,38 @@ export class ViaVersionManager {
|
|
|
24
23
|
|
|
25
24
|
this.logger.info('Setting up ViaVersion, ViaBackwards, ViaRewind...');
|
|
26
25
|
|
|
27
|
-
await this.
|
|
28
|
-
|
|
26
|
+
await this.cleanupRemappedFolders(pluginsDir);
|
|
29
27
|
await this.downloadViaVersion(pluginsDir);
|
|
28
|
+
|
|
29
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
30
|
+
|
|
30
31
|
await this.downloadViaBackwards(pluginsDir);
|
|
31
32
|
await this.downloadViaRewind(pluginsDir);
|
|
32
33
|
|
|
33
|
-
await this.verifyAllPlugins(pluginsDir);
|
|
34
|
-
|
|
35
34
|
this.logger.success('ViaVersion suite installed successfully');
|
|
36
|
-
this.logger.info('Players from older versions can now connect to your server');
|
|
37
35
|
}
|
|
38
36
|
|
|
39
|
-
private async
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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
|
-
}
|
|
37
|
+
private async cleanupRemappedFolders(pluginsDir: string): Promise<void> {
|
|
38
|
+
try {
|
|
39
|
+
const files = await fs.readdir(pluginsDir);
|
|
40
|
+
for (const file of files) {
|
|
41
|
+
if (file.includes('.paper-remapped')) {
|
|
42
|
+
const remappedPath = path.join(pluginsDir, file);
|
|
43
|
+
const stat = await fs.stat(remappedPath);
|
|
44
|
+
if (stat.isDirectory()) {
|
|
45
|
+
await fs.remove(remappedPath);
|
|
63
46
|
}
|
|
64
|
-
} catch (error) {
|
|
65
|
-
this.logger.warning(`Error checking ${file.name}, removing...`);
|
|
66
|
-
await fs.remove(filePath);
|
|
67
47
|
}
|
|
68
48
|
}
|
|
49
|
+
} catch (error) {
|
|
69
50
|
}
|
|
70
51
|
}
|
|
71
52
|
|
|
72
53
|
private async downloadFile(url: string, destPath: string, fileName: string): Promise<void> {
|
|
54
|
+
if (await FileUtils.fileExists(destPath)) {
|
|
55
|
+
await fs.remove(destPath);
|
|
56
|
+
}
|
|
57
|
+
|
|
73
58
|
this.logger.info(`Downloading ${fileName}...`);
|
|
74
59
|
|
|
75
60
|
try {
|
|
@@ -84,24 +69,16 @@ export class ViaVersionManager {
|
|
|
84
69
|
});
|
|
85
70
|
|
|
86
71
|
const writer = fs.createWriteStream(destPath);
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
await
|
|
90
|
-
writer.on('finish', () => resolve());
|
|
91
|
-
writer.on('error', (err) => reject(err));
|
|
92
|
-
});
|
|
72
|
+
|
|
73
|
+
await pipeline(response.data, writer);
|
|
74
|
+
await finished(writer);
|
|
93
75
|
|
|
94
76
|
const stats = await fs.stat(destPath);
|
|
95
77
|
if (stats.size < 100000) {
|
|
96
78
|
throw new Error(`Downloaded file too small: ${stats.size} bytes`);
|
|
97
79
|
}
|
|
98
80
|
|
|
99
|
-
|
|
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)`);
|
|
81
|
+
this.logger.success(`Downloaded ${fileName} (${(stats.size / 1024 / 1024).toFixed(2)} MB)`);
|
|
105
82
|
|
|
106
83
|
} catch (error) {
|
|
107
84
|
this.logger.error(`Failed to download ${fileName}:`, error);
|
|
@@ -111,74 +88,19 @@ export class ViaVersionManager {
|
|
|
111
88
|
|
|
112
89
|
private async downloadViaVersion(pluginsDir: string): Promise<void> {
|
|
113
90
|
const destPath = path.join(pluginsDir, 'ViaVersion.jar');
|
|
114
|
-
|
|
115
|
-
if (await FileUtils.fileExists(destPath)) {
|
|
116
|
-
await fs.remove(destPath);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
91
|
await this.downloadFile(this.VIAVERSION_URL, destPath, 'ViaVersion.jar');
|
|
120
92
|
}
|
|
121
93
|
|
|
122
94
|
private async downloadViaBackwards(pluginsDir: string): Promise<void> {
|
|
123
95
|
const destPath = path.join(pluginsDir, 'ViaBackwards.jar');
|
|
124
|
-
|
|
125
|
-
if (await FileUtils.fileExists(destPath)) {
|
|
126
|
-
await fs.remove(destPath);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
96
|
await this.downloadFile(this.VIABACKWARDS_URL, destPath, 'ViaBackwards.jar');
|
|
130
97
|
}
|
|
131
98
|
|
|
132
99
|
private async downloadViaRewind(pluginsDir: string): Promise<void> {
|
|
133
100
|
const destPath = path.join(pluginsDir, 'ViaRewind.jar');
|
|
134
|
-
|
|
135
|
-
if (await FileUtils.fileExists(destPath)) {
|
|
136
|
-
await fs.remove(destPath);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
101
|
await this.downloadFile(this.VIAREWIND_URL, destPath, 'ViaRewind.jar');
|
|
140
102
|
}
|
|
141
103
|
|
|
142
|
-
private async verifyAllPlugins(pluginsDir: string): Promise<void> {
|
|
143
|
-
const files = ['ViaVersion.jar', 'ViaBackwards.jar', 'ViaRewind.jar'];
|
|
144
|
-
let allValid = true;
|
|
145
|
-
|
|
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
|
-
}
|
|
176
|
-
|
|
177
|
-
if (!allValid) {
|
|
178
|
-
throw new Error('Some ViaVersion plugins are corrupt or missing');
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
104
|
public async configureViaVersion(config: MinecraftConfig): Promise<void> {
|
|
183
105
|
const pluginsDir = config.folders.plugins;
|
|
184
106
|
const viaConfigDir = path.join(pluginsDir, 'ViaVersion');
|
|
@@ -187,8 +109,6 @@ export class ViaVersionManager {
|
|
|
187
109
|
const configFile = path.join(viaConfigDir, 'config.yml');
|
|
188
110
|
|
|
189
111
|
const configContent = `# ViaVersion Configuration
|
|
190
|
-
# Auto-generated by mc-headless
|
|
191
|
-
|
|
192
112
|
enable-client-side-block-updates: true
|
|
193
113
|
prevent-collision: true
|
|
194
114
|
auto-team: true
|
|
@@ -209,6 +129,5 @@ use-natives: true
|
|
|
209
129
|
`;
|
|
210
130
|
|
|
211
131
|
await FileUtils.writeFile(configFile, configContent);
|
|
212
|
-
this.logger.debug('ViaVersion configuration created');
|
|
213
132
|
}
|
|
214
133
|
}
|
package/src/types/index.ts
CHANGED
|
@@ -88,4 +88,210 @@ export interface Player {
|
|
|
88
88
|
ip: string;
|
|
89
89
|
ping: number;
|
|
90
90
|
connectedAt: Date;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export interface JavaInfo {
|
|
94
|
+
path: string;
|
|
95
|
+
version: string;
|
|
96
|
+
type: 'system' | 'portable';
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export interface GeyserConfig {
|
|
100
|
+
bedrock: {
|
|
101
|
+
port: number;
|
|
102
|
+
address: string;
|
|
103
|
+
};
|
|
104
|
+
remote: {
|
|
105
|
+
address: string;
|
|
106
|
+
port: number;
|
|
107
|
+
authType: string;
|
|
108
|
+
};
|
|
109
|
+
floodgateKeyFile: string;
|
|
110
|
+
passthroughMotd: boolean;
|
|
111
|
+
passthroughPlayerCounts: boolean;
|
|
112
|
+
passthroughProtocolName: boolean;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export interface ViaVersionConfig {
|
|
116
|
+
enableClientSideBlockUpdates: boolean;
|
|
117
|
+
preventCollision: boolean;
|
|
118
|
+
autoTeam: boolean;
|
|
119
|
+
suppressMetadataErrors: boolean;
|
|
120
|
+
enableLegacyServerPing: boolean;
|
|
121
|
+
blockConnectionMethod: boolean;
|
|
122
|
+
nmsPlayerTicking: boolean;
|
|
123
|
+
debug: boolean;
|
|
124
|
+
maxPps: number;
|
|
125
|
+
maxPpInterval: number;
|
|
126
|
+
fixSelfRendering: boolean;
|
|
127
|
+
fixLowLevelCollision: boolean;
|
|
128
|
+
shieldBlocking: boolean;
|
|
129
|
+
fixInfestedBlockBreaking: boolean;
|
|
130
|
+
ignoreLong1_16Channel: boolean;
|
|
131
|
+
forceJsonTransform: boolean;
|
|
132
|
+
useNatives: boolean;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export interface SkinRestorerConfig {
|
|
136
|
+
enabled: boolean;
|
|
137
|
+
updateSkins: boolean;
|
|
138
|
+
allowDefaultSkins: boolean;
|
|
139
|
+
allowCustomSkins: boolean;
|
|
140
|
+
allowThirdParty: boolean;
|
|
141
|
+
skinCacheSize: number;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export interface PluginInfo {
|
|
145
|
+
name: string;
|
|
146
|
+
version: string;
|
|
147
|
+
enabled: boolean;
|
|
148
|
+
main: string;
|
|
149
|
+
authors: string[];
|
|
150
|
+
website?: string;
|
|
151
|
+
description?: string;
|
|
152
|
+
depends?: string[];
|
|
153
|
+
softDepends?: string[];
|
|
154
|
+
loadBefore?: string[];
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export interface WorldInfo {
|
|
158
|
+
name: string;
|
|
159
|
+
size: number;
|
|
160
|
+
players: number;
|
|
161
|
+
loadedChunks: number;
|
|
162
|
+
entities: number;
|
|
163
|
+
tiles: number;
|
|
164
|
+
seed: string;
|
|
165
|
+
difficulty: Difficulty;
|
|
166
|
+
gamemode: Gamemode;
|
|
167
|
+
hardcore: boolean;
|
|
168
|
+
spawn: {
|
|
169
|
+
x: number;
|
|
170
|
+
y: number;
|
|
171
|
+
z: number;
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export interface BackupOptions {
|
|
176
|
+
type: 'full' | 'world' | 'plugins' | 'config';
|
|
177
|
+
compression: 'none' | 'gzip' | 'zip';
|
|
178
|
+
includePlayerData: boolean;
|
|
179
|
+
maxBackups: number;
|
|
180
|
+
retentionDays: number;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export interface RamdiskConfig {
|
|
184
|
+
enabled: boolean;
|
|
185
|
+
world: boolean;
|
|
186
|
+
plugins: boolean;
|
|
187
|
+
addons: boolean;
|
|
188
|
+
backupInterval: number;
|
|
189
|
+
masterStorage: string;
|
|
190
|
+
size: string;
|
|
191
|
+
mountPoint: string;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export interface SymlinkConfig {
|
|
195
|
+
enabled: boolean;
|
|
196
|
+
masterPath: string;
|
|
197
|
+
worlds: boolean;
|
|
198
|
+
plugins: boolean;
|
|
199
|
+
addons: boolean;
|
|
200
|
+
mods: boolean;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export interface NetworkOptimizationConfig {
|
|
204
|
+
tcpFastOpen: boolean;
|
|
205
|
+
tcpNoDelay: boolean;
|
|
206
|
+
preferIPv4: boolean;
|
|
207
|
+
compressionThreshold: number;
|
|
208
|
+
bungeeMode: boolean;
|
|
209
|
+
proxyProtocol: boolean;
|
|
210
|
+
velocity?: {
|
|
211
|
+
enabled: boolean;
|
|
212
|
+
secret: string;
|
|
213
|
+
forwardingMode: 'legacy' | 'modern';
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export interface MemoryMonitorConfig {
|
|
218
|
+
enabled: boolean;
|
|
219
|
+
threshold: number;
|
|
220
|
+
interval: number;
|
|
221
|
+
action: 'restart' | 'stop' | 'warn';
|
|
222
|
+
maxMemoryLeakRestarts: number;
|
|
223
|
+
gcOnWarning: boolean;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
export interface OwnerConfig {
|
|
227
|
+
usernames: string[];
|
|
228
|
+
prefix: string;
|
|
229
|
+
enabled: boolean;
|
|
230
|
+
permissions: string[];
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export interface PterodactylConfig {
|
|
234
|
+
autoDetect: boolean;
|
|
235
|
+
useSystemJava: boolean;
|
|
236
|
+
respectPortEnv: boolean;
|
|
237
|
+
respectMemoryEnv: boolean;
|
|
238
|
+
cleanupRemapped: boolean;
|
|
239
|
+
warnUdp: boolean;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
export interface PluginManagerConfig {
|
|
243
|
+
autoUpdate: boolean;
|
|
244
|
+
verifyOnLoad: boolean;
|
|
245
|
+
cleanupCorrupt: boolean;
|
|
246
|
+
downloadDelay: number;
|
|
247
|
+
retryCount: number;
|
|
248
|
+
retryDelay: number;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
export interface ViaVersionManagerConfig {
|
|
252
|
+
autoDownload: boolean;
|
|
253
|
+
autoUpdate: boolean;
|
|
254
|
+
configureAutomatically: boolean;
|
|
255
|
+
downloadDelay: number;
|
|
256
|
+
versions: {
|
|
257
|
+
viaversion: string;
|
|
258
|
+
viabackwards: string;
|
|
259
|
+
viarewind: string;
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
export interface SkinRestorerManagerConfig {
|
|
264
|
+
autoDownload: boolean;
|
|
265
|
+
autoUpdate: boolean;
|
|
266
|
+
configureAutomatically: boolean;
|
|
267
|
+
downloadUrl: string;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
export interface MinecraftServerOptions extends Partial<MinecraftConfig> {
|
|
271
|
+
enableViaVersion?: boolean;
|
|
272
|
+
enableViaBackwards?: boolean;
|
|
273
|
+
enableViaRewind?: boolean;
|
|
274
|
+
enableSkinRestorer?: boolean;
|
|
275
|
+
enableProtocolSupport?: boolean;
|
|
276
|
+
enableProtocolLib?: boolean;
|
|
277
|
+
enableTCPShield?: boolean;
|
|
278
|
+
enableSpigotOptimizers?: boolean;
|
|
279
|
+
enableSpark?: boolean;
|
|
280
|
+
enableViewDistanceTweaks?: boolean;
|
|
281
|
+
enableFarmControl?: boolean;
|
|
282
|
+
enableEntityDetection?: boolean;
|
|
283
|
+
customJavaArgs?: string[];
|
|
284
|
+
javaVersion?: '17' | '21' | 'auto';
|
|
285
|
+
usePortableJava?: boolean;
|
|
286
|
+
memoryMonitor?: MemoryMonitorConfig;
|
|
287
|
+
autoInstallJava?: boolean;
|
|
288
|
+
networkOptimization?: NetworkOptimizationConfig;
|
|
289
|
+
owners?: string[];
|
|
290
|
+
ownerCommands?: OwnerConfig;
|
|
291
|
+
silentMode?: boolean;
|
|
292
|
+
statsInterval?: number;
|
|
293
|
+
cleanLogsInterval?: number;
|
|
294
|
+
optimizeForPterodactyl?: boolean;
|
|
295
|
+
ramdisk?: RamdiskConfig;
|
|
296
|
+
symlinkMaster?: string;
|
|
91
297
|
}
|