@polymer505/msc 1.3.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/LICENSE +21 -0
- package/README.md +96 -0
- package/index.js +238 -0
- package/package.json +54 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Polymer-505
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# msc (Minecraft Server Creator)
|
|
2
|
+
|
|
3
|
+
Command-line tool for downloading popular Minecraft server jars.
|
|
4
|
+
|
|
5
|
+
<p align="center">
|
|
6
|
+
<img src="./cli-preview.gif" alt="msc preview" width="900">
|
|
7
|
+
</p>
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- Downloads server kernels directly from official sources (`vanilla`, `paper`, `purpur`, `fabric`, `forge`).
|
|
12
|
+
- Automatically generates `eula.txt`.
|
|
13
|
+
- Creates launch scripts (`start.sh` for Linux or `start.bat` for Windows) with pre-configured **Aikar's Flags**.
|
|
14
|
+
- Auto-detects OS platform to generate the correct executable script.
|
|
15
|
+
|
|
16
|
+
> **Note on Forge:** Forge doesn't distribute a ready-to-run server jar. Instead, `msc` downloads the official Forge installer and runs it automatically (`java -jar forge.jar --installServer`). This requires Java to be installed and available in your `PATH`. No `start.sh`/`start.bat` is generated for Forge — use the run script that the Forge installer creates.
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
Run `msc` by specifying the kernel, Minecraft version, and allocated RAM:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
msc <kernel> <version> <ram>
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Examples
|
|
27
|
+
|
|
28
|
+
- Vanilla
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
msc vanilla 1.21.11 2G
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
- Paper
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
msc paper 1.19.2 5G
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
- Purpur
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
msc purpur 26.2 4G
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
- Fabric
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
msc fabric 1.16.5 4G
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
- Forge
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
msc forge 1.20.1 5G
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Building from Source
|
|
59
|
+
|
|
60
|
+
If you want to compile `msc` into a standalone executable file, use `@yao-pkg/pkg`:
|
|
61
|
+
|
|
62
|
+
1. **Install dependencies:**
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
npm install
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
2. **Build executables:**
|
|
69
|
+
|
|
70
|
+
- For linux (msc-linux)
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
npm run build
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
- For linux arm64 (msc-linux-arm64)
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
npm run build-arm64
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
- For Windows (msc-win.exe)
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
npm run build:win
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
- For Windows arm64 (msc-win-arm64.exe)
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
npm run build:win-arm64
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## License
|
|
95
|
+
|
|
96
|
+
This project is licensed under the [MIT License](LICENSE).
|
package/index.js
ADDED
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require("fs");
|
|
4
|
+
const child_process = require("child_process");
|
|
5
|
+
const { pipeline } = require("stream/promises");
|
|
6
|
+
const { Readable } = require("stream");
|
|
7
|
+
const cliProgress = require("cli-progress");
|
|
8
|
+
const pc = require("picocolors");
|
|
9
|
+
|
|
10
|
+
// Arguments
|
|
11
|
+
const [kernel, version, ram] = process.argv.slice(2);
|
|
12
|
+
|
|
13
|
+
// Link to the kernels api
|
|
14
|
+
const api_link = {
|
|
15
|
+
vanilla: "https://launchermeta.mojang.com/mc/game/version_manifest.json",
|
|
16
|
+
paper: "https://fill.papermc.io/v3/projects/paper",
|
|
17
|
+
purpur: "https://api.purpurmc.org/v2/purpur",
|
|
18
|
+
fabric: "https://meta.fabricmc.net/v2/versions",
|
|
19
|
+
forge: "https://files.minecraftforge.net/net/minecraftforge/forge",
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
// Open help
|
|
23
|
+
if (kernel === "-help" || !kernel) {
|
|
24
|
+
console.log("Usage: msc <kernel> <version> <ram>");
|
|
25
|
+
console.log("Example: msc paper 1.20.4 4G");
|
|
26
|
+
console.log("Available commands: -help, -list");
|
|
27
|
+
process.exit(0);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// List kernels
|
|
31
|
+
if (kernel === "-list") {
|
|
32
|
+
console.log("Available kernels: vanilla, paper, purpur, fabric, forge");
|
|
33
|
+
process.exit(0);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Validate required arguments
|
|
37
|
+
if (!version || !ram) {
|
|
38
|
+
console.log(pc.red("Error: missing required arguments"));
|
|
39
|
+
console.log("Usage: msc <kernel> <version> <ram>");
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Validate ram format (e.g. "4G" or "4096M")
|
|
44
|
+
const ramMatch = ram.match(/^(\d+)([GM])$/i);
|
|
45
|
+
if (!ramMatch) {
|
|
46
|
+
console.log(
|
|
47
|
+
pc.red(`Error: invalid ram format "${ram}", expected e.g. "4G" or "4096M"`),
|
|
48
|
+
);
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Get vanilla kernel link
|
|
53
|
+
function getVanillaUrl(version) {
|
|
54
|
+
return fetch(api_link.vanilla)
|
|
55
|
+
.then((response) => response.json())
|
|
56
|
+
.then((data) => {
|
|
57
|
+
const info = data.versions.find((item) => item.id === version);
|
|
58
|
+
if (!info) {
|
|
59
|
+
console.log(pc.red(`Error: version ${version} not found`));
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
return info;
|
|
63
|
+
})
|
|
64
|
+
.then((info) => fetch(info.url))
|
|
65
|
+
.then((response) => response.json())
|
|
66
|
+
.then((data) => data.downloads.server.url);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Get paper kernel link
|
|
70
|
+
function getPaperUrl(version) {
|
|
71
|
+
return fetch(`${api_link.paper}/versions/${version}/builds`)
|
|
72
|
+
.then((response) => response.json())
|
|
73
|
+
.then((ids) => {
|
|
74
|
+
if (ids.ok === false) {
|
|
75
|
+
console.log(pc.red(`Error: version ${version} not found`));
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
return ids[0].id;
|
|
79
|
+
})
|
|
80
|
+
.then((latestId) =>
|
|
81
|
+
fetch(`${api_link.paper}/versions/${version}/builds/${latestId}`),
|
|
82
|
+
)
|
|
83
|
+
.then((response) => response.json())
|
|
84
|
+
.then((data) => data.downloads["server:default"].url);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Get purpur kernel link
|
|
88
|
+
function getPurpurUrl(version) {
|
|
89
|
+
return fetch(`${api_link.purpur}/${version}`)
|
|
90
|
+
.then((response) => response.json())
|
|
91
|
+
.then((data) => {
|
|
92
|
+
if (!data.builds) {
|
|
93
|
+
console.log(pc.red(`Error: version ${version} not found`));
|
|
94
|
+
process.exit(1);
|
|
95
|
+
}
|
|
96
|
+
const latestBuild = data.builds.latest;
|
|
97
|
+
return `${api_link.purpur}/${version}/${latestBuild}/download`;
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Get fabric kernel link
|
|
102
|
+
function getFabricUrl(version) {
|
|
103
|
+
return Promise.all([
|
|
104
|
+
fetch(`${api_link.fabric}/loader/${version}`).then((response) =>
|
|
105
|
+
response.json(),
|
|
106
|
+
),
|
|
107
|
+
fetch(`${api_link.fabric}/installer`).then((response) => response.json()),
|
|
108
|
+
]).then(([loaderData, installerData]) => {
|
|
109
|
+
if (!loaderData || loaderData.length === 0) {
|
|
110
|
+
console.log(pc.red(`Error: version ${version} not found`));
|
|
111
|
+
process.exit(1);
|
|
112
|
+
}
|
|
113
|
+
const latestBuild = loaderData[0].loader.version;
|
|
114
|
+
const installerVersion = installerData[0].version;
|
|
115
|
+
return `${api_link.fabric}/loader/${version}/${latestBuild}/${installerVersion}/server/jar`;
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Get forge kernel link
|
|
120
|
+
function getForgeUrl(version) {
|
|
121
|
+
return fetch(`${api_link.forge}/promotions_slim.json`)
|
|
122
|
+
.then((response) => response.json())
|
|
123
|
+
.then((data) => {
|
|
124
|
+
const latestBuild = data.promos[`${version}-latest`];
|
|
125
|
+
if (!latestBuild) {
|
|
126
|
+
console.log(pc.red(`Error: version ${version} not found`));
|
|
127
|
+
process.exit(1);
|
|
128
|
+
}
|
|
129
|
+
return `https://maven.minecraftforge.net/net/minecraftforge/forge/${version}-${latestBuild}/forge-${version}-${latestBuild}-installer.jar`;
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Create start.sh or start.bat
|
|
134
|
+
function createStartSh(kernelName) {
|
|
135
|
+
const ramMatch = ram.match(/^(\d+)([GM])$/i);
|
|
136
|
+
const [, amount, unit] = ramMatch;
|
|
137
|
+
const ramInMb =
|
|
138
|
+
unit.toUpperCase() === "G" ? parseInt(amount) * 1024 : parseInt(amount);
|
|
139
|
+
|
|
140
|
+
if (process.platform === "win32") {
|
|
141
|
+
fs.writeFileSync(
|
|
142
|
+
"start.bat",
|
|
143
|
+
`java -Xms${ramInMb}M -Xmx${ramInMb}M --add-modules=jdk.incubator.vector -XX:+UseG1GC -XX:+ParallelRefProcEnabled -XX:MaxGCPauseMillis=200 -XX:+UnlockExperimentalVMOptions -XX:+DisableExplicitGC -XX:+AlwaysPreTouch -XX:G1HeapWastePercent=5 -XX:G1MixedGCCountTarget=4 -XX:InitiatingHeapOccupancyPercent=15 -XX:G1MixedGCLiveThresholdPercent=90 -XX:G1RSetUpdatingPauseTimePercent=5 -XX:SurvivorRatio=32 -XX:+PerfDisableSharedMem -XX:MaxTenuringThreshold=1 -Dusing.aikars.flags=https://mcflags.emc.gs -Daikars.new.flags=true -XX:G1NewSizePercent=30 -XX:G1MaxNewSizePercent=40 -XX:G1HeapRegionSize=8M -XX:G1ReservePercent=20 -jar ${kernelName}.jar nogui`,
|
|
144
|
+
);
|
|
145
|
+
console.log("File start.bat created successful");
|
|
146
|
+
} else {
|
|
147
|
+
fs.writeFileSync(
|
|
148
|
+
"start.sh",
|
|
149
|
+
`#!/bin/bash
|
|
150
|
+
java -Xms${ramInMb}M -Xmx${ramInMb}M --add-modules=jdk.incubator.vector -XX:+UseG1GC -XX:+ParallelRefProcEnabled -XX:MaxGCPauseMillis=200 -XX:+UnlockExperimentalVMOptions -XX:+DisableExplicitGC -XX:+AlwaysPreTouch -XX:G1HeapWastePercent=5 -XX:G1MixedGCCountTarget=4 -XX:InitiatingHeapOccupancyPercent=15 -XX:G1MixedGCLiveThresholdPercent=90 -XX:G1RSetUpdatingPauseTimePercent=5 -XX:SurvivorRatio=32 -XX:+PerfDisableSharedMem -XX:MaxTenuringThreshold=1 -Dusing.aikars.flags=https://mcflags.emc.gs -Daikars.new.flags=true -XX:G1NewSizePercent=30 -XX:G1MaxNewSizePercent=40 -XX:G1HeapRegionSize=8M -XX:G1ReservePercent=20 -jar ${kernelName}.jar nogui`,
|
|
151
|
+
);
|
|
152
|
+
fs.chmodSync("start.sh", 0o755);
|
|
153
|
+
console.log(pc.green("File start.sh created successful"));
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Create eula.txt
|
|
158
|
+
function createEulaTxt() {
|
|
159
|
+
fs.writeFileSync("eula.txt", "eula=true");
|
|
160
|
+
console.log(pc.green("File eula.txt created successful"));
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function downloadKernel(kernelName, version, getUrlFn) {
|
|
164
|
+
getUrlFn(version)
|
|
165
|
+
.then((downloadUrl) => {
|
|
166
|
+
console.log(`Downloading ${kernelName}...`);
|
|
167
|
+
return fetch(downloadUrl);
|
|
168
|
+
})
|
|
169
|
+
.then((response) => {
|
|
170
|
+
if (response.status !== 200) {
|
|
171
|
+
console.log(
|
|
172
|
+
pc.red(`Error downloading: server return code ${response.status}`),
|
|
173
|
+
);
|
|
174
|
+
process.exit(1);
|
|
175
|
+
}
|
|
176
|
+
const totalSize =
|
|
177
|
+
parseInt(response.headers.get("content-length"), 10) || 0;
|
|
178
|
+
const progressBar = new cliProgress.SingleBar(
|
|
179
|
+
{},
|
|
180
|
+
cliProgress.Presets.shades_classic,
|
|
181
|
+
);
|
|
182
|
+
progressBar.start(totalSize, 0);
|
|
183
|
+
|
|
184
|
+
const nodeStream = Readable.fromWeb(response.body);
|
|
185
|
+
nodeStream.on("data", (chunk) => {
|
|
186
|
+
progressBar.increment(chunk.length);
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
return pipeline(
|
|
190
|
+
nodeStream,
|
|
191
|
+
fs.createWriteStream(`${kernelName}.jar`),
|
|
192
|
+
).then(() => progressBar.stop());
|
|
193
|
+
})
|
|
194
|
+
.then(() => console.log(pc.green(`${kernelName}.jar download successful`)))
|
|
195
|
+
.then(() => {
|
|
196
|
+
if (kernelName === "forge") {
|
|
197
|
+
console.log("Starting the forge installation");
|
|
198
|
+
child_process.execSync("java -jar forge.jar --installServer", {
|
|
199
|
+
stdio: "inherit",
|
|
200
|
+
});
|
|
201
|
+
fs.rmSync("forge.jar");
|
|
202
|
+
fs.rmSync("forge.jar.log", { force: true });
|
|
203
|
+
} else {
|
|
204
|
+
createStartSh(kernelName);
|
|
205
|
+
}
|
|
206
|
+
createEulaTxt();
|
|
207
|
+
})
|
|
208
|
+
.catch((error) => {
|
|
209
|
+
console.error(pc.red("Error downloading:"), error);
|
|
210
|
+
process.exit(1);
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
switch (kernel) {
|
|
215
|
+
case "vanilla":
|
|
216
|
+
console.log(`Vanilla ${version} has been selected`);
|
|
217
|
+
downloadKernel("vanilla", version, getVanillaUrl);
|
|
218
|
+
break;
|
|
219
|
+
case "paper":
|
|
220
|
+
console.log(`Paper ${version} has been selected`);
|
|
221
|
+
downloadKernel("paper", version, getPaperUrl);
|
|
222
|
+
break;
|
|
223
|
+
case "purpur":
|
|
224
|
+
console.log(`Purpur ${version} has been selected`);
|
|
225
|
+
downloadKernel("purpur", version, getPurpurUrl);
|
|
226
|
+
break;
|
|
227
|
+
case "fabric":
|
|
228
|
+
console.log(`Fabric ${version} has been selected`);
|
|
229
|
+
downloadKernel("fabric", version, getFabricUrl);
|
|
230
|
+
break;
|
|
231
|
+
case "forge":
|
|
232
|
+
console.log(`Forge ${version} has been selected`);
|
|
233
|
+
downloadKernel("forge", version, getForgeUrl);
|
|
234
|
+
break;
|
|
235
|
+
default:
|
|
236
|
+
console.log(pc.red(`Unknown kernel ${kernel}`));
|
|
237
|
+
process.exit(1);
|
|
238
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@polymer505/msc",
|
|
3
|
+
"version": "1.3.0",
|
|
4
|
+
"description": "Command-line tool for downloading popular Minecraft server jars.",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/Polymer-505/msc"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://github.com/Polymer-505/msc#readme",
|
|
10
|
+
"bugs": {
|
|
11
|
+
"url": "https://github.com/Polymer-505/msc/issues"
|
|
12
|
+
},
|
|
13
|
+
"main": "index.js",
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build:win": "pkg index.js --targets latest-win-x64 --output ./build/msc-win.exe",
|
|
16
|
+
"build:win-arm64": "pkg index.js --targets latest-win-arm64 --output ./build/msc-win-arm64.exe",
|
|
17
|
+
"build": "pkg index.js --targets latest-linux-x64 --output ./build/msc-linux",
|
|
18
|
+
"build-arm64": "pkg index.js --targets latest-linux-arm64 --output ./build/msc-linux-arm64"
|
|
19
|
+
},
|
|
20
|
+
"bin": {
|
|
21
|
+
"msc": "./index.js"
|
|
22
|
+
},
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": ">=18"
|
|
25
|
+
},
|
|
26
|
+
"files": [
|
|
27
|
+
"index.js",
|
|
28
|
+
"LICENSE"
|
|
29
|
+
],
|
|
30
|
+
"keywords": [
|
|
31
|
+
"minecraft",
|
|
32
|
+
"minecraft-server",
|
|
33
|
+
"cli",
|
|
34
|
+
"minecraft-server-creator",
|
|
35
|
+
"paper",
|
|
36
|
+
"purpur",
|
|
37
|
+
"fabric",
|
|
38
|
+
"forge",
|
|
39
|
+
"vanilla",
|
|
40
|
+
"aikar-flags",
|
|
41
|
+
"download",
|
|
42
|
+
"automation"
|
|
43
|
+
],
|
|
44
|
+
"author": "Polymer-505",
|
|
45
|
+
"license": "MIT",
|
|
46
|
+
"type": "commonjs",
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@yao-pkg/pkg": "^6.22.0"
|
|
49
|
+
},
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"cli-progress": "^3.12.0",
|
|
52
|
+
"picocolors": "^1.1.1"
|
|
53
|
+
}
|
|
54
|
+
}
|