adds forge support, fixes some critical errors

This commit is contained in:
Emmaline Autumn 2023-10-08 13:38:00 -06:00
parent 6944cbb9f7
commit ad4629576c
21 changed files with 3484 additions and 132 deletions

4
.gitignore vendored
View File

@ -10,8 +10,8 @@ _fresh/
# JAR files in case one shows up
**/*.jar
fabric/
forge/
./fabric/
./forge/
vanilla/
server/

View File

@ -19,4 +19,6 @@ RUN export JAVA_HOME
EXPOSE 8000
EXPOSE 25565-25575
VOLUME [ "/mcgrizz" ]
CMD [ "run", "-A", "main.ts" ]

1
cache/gameVersions.json vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -6,7 +6,7 @@
"build": "deno run -A dev.ts build",
"preview": "deno run -A main.ts",
"update": "deno run -A -r https://fresh.deno.dev/update .",
"clean": "rm -rf ./server && rm ./players.cache.json && rm ./mcgrizz.json"
"clean": "rm -rf ./server && rm ./mcgrizz.json && rm ./players.cache.json"
},
"lint": {
"rules": {
@ -33,7 +33,8 @@
"@preact/signals-core": "https://esm.sh/*@preact/signals-core@1.2.3",
"$std/": "https://deno.land/std@0.193.0/",
"puppet": "https://deno.land/x/sockpuppet@0.6.1/mod.ts",
"puppet/client": "https://deno.land/x/sockpuppet@0.6.1/client/mod.ts"
"puppet/client": "https://deno.land/x/sockpuppet@0.6.1/client/mod.ts",
"jsdom": "https://esm.sh/jsdom"
},
"compilerOptions": {
"jsx": "react-jsx",

1238
fabric/versions/game.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,362 @@
[
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.11.2/fabric-installer-0.11.2.jar",
"maven": "net.fabricmc:fabric-installer:0.11.2",
"version": "0.11.2",
"stable": true
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.11.1/fabric-installer-0.11.1.jar",
"maven": "net.fabricmc:fabric-installer:0.11.1",
"version": "0.11.1",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.11.0/fabric-installer-0.11.0.jar",
"maven": "net.fabricmc:fabric-installer:0.11.0",
"version": "0.11.0",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.10.2/fabric-installer-0.10.2.jar",
"maven": "net.fabricmc:fabric-installer:0.10.2",
"version": "0.10.2",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.10.1/fabric-installer-0.10.1.jar",
"maven": "net.fabricmc:fabric-installer:0.10.1",
"version": "0.10.1",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.10.0/fabric-installer-0.10.0.jar",
"maven": "net.fabricmc:fabric-installer:0.10.0",
"version": "0.10.0",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.9.1/fabric-installer-0.9.1.jar",
"maven": "net.fabricmc:fabric-installer:0.9.1",
"version": "0.9.1",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.9.0/fabric-installer-0.9.0.jar",
"maven": "net.fabricmc:fabric-installer:0.9.0",
"version": "0.9.0",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.8.3/fabric-installer-0.8.3.jar",
"maven": "net.fabricmc:fabric-installer:0.8.3",
"version": "0.8.3",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.8.2/fabric-installer-0.8.2.jar",
"maven": "net.fabricmc:fabric-installer:0.8.2",
"version": "0.8.2",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.8.1/fabric-installer-0.8.1.jar",
"maven": "net.fabricmc:fabric-installer:0.8.1",
"version": "0.8.1",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.8.0/fabric-installer-0.8.0.jar",
"maven": "net.fabricmc:fabric-installer:0.8.0",
"version": "0.8.0",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.7.4/fabric-installer-0.7.4.jar",
"maven": "net.fabricmc:fabric-installer:0.7.4",
"version": "0.7.4",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.7.3/fabric-installer-0.7.3.jar",
"maven": "net.fabricmc:fabric-installer:0.7.3",
"version": "0.7.3",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.7.2/fabric-installer-0.7.2.jar",
"maven": "net.fabricmc:fabric-installer:0.7.2",
"version": "0.7.2",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.7.1/fabric-installer-0.7.1.jar",
"maven": "net.fabricmc:fabric-installer:0.7.1",
"version": "0.7.1",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.6.1.51/fabric-installer-0.6.1.51.jar",
"maven": "net.fabricmc:fabric-installer:0.6.1.51",
"version": "0.6.1.51",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.6.1.50/fabric-installer-0.6.1.50.jar",
"maven": "net.fabricmc:fabric-installer:0.6.1.50",
"version": "0.6.1.50",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.6.1.49/fabric-installer-0.6.1.49.jar",
"maven": "net.fabricmc:fabric-installer:0.6.1.49",
"version": "0.6.1.49",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.6.1.48/fabric-installer-0.6.1.48.jar",
"maven": "net.fabricmc:fabric-installer:0.6.1.48",
"version": "0.6.1.48",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.6.1.47/fabric-installer-0.6.1.47.jar",
"maven": "net.fabricmc:fabric-installer:0.6.1.47",
"version": "0.6.1.47",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.6.1.46/fabric-installer-0.6.1.46.jar",
"maven": "net.fabricmc:fabric-installer:0.6.1.46",
"version": "0.6.1.46",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.6.1.45/fabric-installer-0.6.1.45.jar",
"maven": "net.fabricmc:fabric-installer:0.6.1.45",
"version": "0.6.1.45",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.6.1.44/fabric-installer-0.6.1.44.jar",
"maven": "net.fabricmc:fabric-installer:0.6.1.44",
"version": "0.6.1.44",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.6.0.43/fabric-installer-0.6.0.43.jar",
"maven": "net.fabricmc:fabric-installer:0.6.0.43",
"version": "0.6.0.43",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.6.0.42/fabric-installer-0.6.0.42.jar",
"maven": "net.fabricmc:fabric-installer:0.6.0.42",
"version": "0.6.0.42",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.6.0.41/fabric-installer-0.6.0.41.jar",
"maven": "net.fabricmc:fabric-installer:0.6.0.41",
"version": "0.6.0.41",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.5.2.40/fabric-installer-0.5.2.40.jar",
"maven": "net.fabricmc:fabric-installer:0.5.2.40",
"version": "0.5.2.40",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.5.2.39/fabric-installer-0.5.2.39.jar",
"maven": "net.fabricmc:fabric-installer:0.5.2.39",
"version": "0.5.2.39",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.5.2.38/fabric-installer-0.5.2.38.jar",
"maven": "net.fabricmc:fabric-installer:0.5.2.38",
"version": "0.5.2.38",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.5.1.37/fabric-installer-0.5.1.37.jar",
"maven": "net.fabricmc:fabric-installer:0.5.1.37",
"version": "0.5.1.37",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.5.1.36/fabric-installer-0.5.1.36.jar",
"maven": "net.fabricmc:fabric-installer:0.5.1.36",
"version": "0.5.1.36",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.5.0.35/fabric-installer-0.5.0.35.jar",
"maven": "net.fabricmc:fabric-installer:0.5.0.35",
"version": "0.5.0.35",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.5.0.34/fabric-installer-0.5.0.34.jar",
"maven": "net.fabricmc:fabric-installer:0.5.0.34",
"version": "0.5.0.34",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.5.0.33/fabric-installer-0.5.0.33.jar",
"maven": "net.fabricmc:fabric-installer:0.5.0.33",
"version": "0.5.0.33",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.5.0.32/fabric-installer-0.5.0.32.jar",
"maven": "net.fabricmc:fabric-installer:0.5.0.32",
"version": "0.5.0.32",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.5.0.31/fabric-installer-0.5.0.31.jar",
"maven": "net.fabricmc:fabric-installer:0.5.0.31",
"version": "0.5.0.31",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.5.0.30/fabric-installer-0.5.0.30.jar",
"maven": "net.fabricmc:fabric-installer:0.5.0.30",
"version": "0.5.0.30",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.5.0.29/fabric-installer-0.5.0.29.jar",
"maven": "net.fabricmc:fabric-installer:0.5.0.29",
"version": "0.5.0.29",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.4.2.28/fabric-installer-0.4.2.28.jar",
"maven": "net.fabricmc:fabric-installer:0.4.2.28",
"version": "0.4.2.28",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.4.2.27/fabric-installer-0.4.2.27.jar",
"maven": "net.fabricmc:fabric-installer:0.4.2.27",
"version": "0.4.2.27",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.4.2.26/fabric-installer-0.4.2.26.jar",
"maven": "net.fabricmc:fabric-installer:0.4.2.26",
"version": "0.4.2.26",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.4.2.25/fabric-installer-0.4.2.25.jar",
"maven": "net.fabricmc:fabric-installer:0.4.2.25",
"version": "0.4.2.25",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.4.2.24/fabric-installer-0.4.2.24.jar",
"maven": "net.fabricmc:fabric-installer:0.4.2.24",
"version": "0.4.2.24",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.4.2.23/fabric-installer-0.4.2.23.jar",
"maven": "net.fabricmc:fabric-installer:0.4.2.23",
"version": "0.4.2.23",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.4.1.22/fabric-installer-0.4.1.22.jar",
"maven": "net.fabricmc:fabric-installer:0.4.1.22",
"version": "0.4.1.22",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.4.0.21/fabric-installer-0.4.0.21.jar",
"maven": "net.fabricmc:fabric-installer:0.4.0.21",
"version": "0.4.0.21",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.4.0.20/fabric-installer-0.4.0.20.jar",
"maven": "net.fabricmc:fabric-installer:0.4.0.20",
"version": "0.4.0.20",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.4.0.19/fabric-installer-0.4.0.19.jar",
"maven": "net.fabricmc:fabric-installer:0.4.0.19",
"version": "0.4.0.19",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.4.0.18/fabric-installer-0.4.0.18.jar",
"maven": "net.fabricmc:fabric-installer:0.4.0.18",
"version": "0.4.0.18",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.3.0.17/fabric-installer-0.3.0.17.jar",
"maven": "net.fabricmc:fabric-installer:0.3.0.17",
"version": "0.3.0.17",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.3.0.16/fabric-installer-0.3.0.16.jar",
"maven": "net.fabricmc:fabric-installer:0.3.0.16",
"version": "0.3.0.16",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.3.0.15/fabric-installer-0.3.0.15.jar",
"maven": "net.fabricmc:fabric-installer:0.3.0.15",
"version": "0.3.0.15",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.2.4.14/fabric-installer-0.2.4.14.jar",
"maven": "net.fabricmc:fabric-installer:0.2.4.14",
"version": "0.2.4.14",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.2.3.12/fabric-installer-0.2.3.12.jar",
"maven": "net.fabricmc:fabric-installer:0.2.3.12",
"version": "0.2.3.12",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.2.2.11/fabric-installer-0.2.2.11.jar",
"maven": "net.fabricmc:fabric-installer:0.2.2.11",
"version": "0.2.2.11",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.2.2.10/fabric-installer-0.2.2.10.jar",
"maven": "net.fabricmc:fabric-installer:0.2.2.10",
"version": "0.2.2.10",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.2.1.9/fabric-installer-0.2.1.9.jar",
"maven": "net.fabricmc:fabric-installer:0.2.1.9",
"version": "0.2.1.9",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.2.1.8/fabric-installer-0.2.1.8.jar",
"maven": "net.fabricmc:fabric-installer:0.2.1.8",
"version": "0.2.1.8",
"stable": false
},
{
"url": "https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.2.0.7/fabric-installer-0.2.0.7.jar",
"maven": "net.fabricmc:fabric-installer:0.2.0.7",
"version": "0.2.0.7",
"stable": false
}
]

1451
fabric/versions/loader.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -5,46 +5,52 @@
import * as $0 from "./routes/_404.tsx";
import * as $1 from "./routes/_app.tsx";
import * as $2 from "./routes/api/fabric/index.ts";
import * as $3 from "./routes/api/manage.ts";
import * as $4 from "./routes/api/players.ts";
import * as $5 from "./routes/index.tsx";
import * as $6 from "./routes/mods/index.tsx";
import * as $7 from "./routes/players.tsx";
import * as $8 from "./routes/properties.tsx";
import * as $9 from "./routes/setup/eula.tsx";
import * as $10 from "./routes/setup/fabric.tsx";
import * as $11 from "./routes/setup/index.tsx";
import * as $12 from "./routes/terminal.tsx";
import * as $13 from "./routes/upload.ts";
import * as $3 from "./routes/api/forge/index.ts";
import * as $4 from "./routes/api/manage.ts";
import * as $5 from "./routes/api/players.ts";
import * as $6 from "./routes/index.tsx";
import * as $7 from "./routes/mods/index.tsx";
import * as $8 from "./routes/players.tsx";
import * as $9 from "./routes/properties.tsx";
import * as $10 from "./routes/setup/eula.tsx";
import * as $11 from "./routes/setup/fabric.tsx";
import * as $12 from "./routes/setup/forge.tsx";
import * as $13 from "./routes/setup/index.tsx";
import * as $14 from "./routes/terminal.tsx";
import * as $15 from "./routes/upload.ts";
import * as $$0 from "./islands/fabricVersions.tsx";
import * as $$1 from "./islands/fileUploader.tsx";
import * as $$2 from "./islands/players.tsx";
import * as $$3 from "./islands/statusManager.tsx";
import * as $$4 from "./islands/terminal.tsx";
import * as $$2 from "./islands/forgeVersions.tsx";
import * as $$3 from "./islands/players.tsx";
import * as $$4 from "./islands/statusManager.tsx";
import * as $$5 from "./islands/terminal.tsx";
const manifest = {
routes: {
"./routes/_404.tsx": $0,
"./routes/_app.tsx": $1,
"./routes/api/fabric/index.ts": $2,
"./routes/api/manage.ts": $3,
"./routes/api/players.ts": $4,
"./routes/index.tsx": $5,
"./routes/mods/index.tsx": $6,
"./routes/players.tsx": $7,
"./routes/properties.tsx": $8,
"./routes/setup/eula.tsx": $9,
"./routes/setup/fabric.tsx": $10,
"./routes/setup/index.tsx": $11,
"./routes/terminal.tsx": $12,
"./routes/upload.ts": $13,
"./routes/api/forge/index.ts": $3,
"./routes/api/manage.ts": $4,
"./routes/api/players.ts": $5,
"./routes/index.tsx": $6,
"./routes/mods/index.tsx": $7,
"./routes/players.tsx": $8,
"./routes/properties.tsx": $9,
"./routes/setup/eula.tsx": $10,
"./routes/setup/fabric.tsx": $11,
"./routes/setup/forge.tsx": $12,
"./routes/setup/index.tsx": $13,
"./routes/terminal.tsx": $14,
"./routes/upload.ts": $15,
},
islands: {
"./islands/fabricVersions.tsx": $$0,
"./islands/fileUploader.tsx": $$1,
"./islands/players.tsx": $$2,
"./islands/statusManager.tsx": $$3,
"./islands/terminal.tsx": $$4,
"./islands/forgeVersions.tsx": $$2,
"./islands/players.tsx": $$3,
"./islands/statusManager.tsx": $$4,
"./islands/terminal.tsx": $$5,
},
baseUrl: import.meta.url,
};

60
islands/forgeVersions.tsx Normal file
View File

@ -0,0 +1,60 @@
import { useEffect, useState } from "preact/hooks";
import { Loader } from "../components/Loader.tsx";
import { Button } from "../components/Button.tsx";
import { ModrinthGameVersion } from "../lib/modrinth.ts";
export function ForgeVersions() {
const [game, setGame] = useState<ModrinthGameVersion[]>([]);
const [isLoading, setIsLoading] = useState(true);
const [includeSnapshots, setIncludeSnapshots] = useState(false);
useEffect(() => {
let poll: number;
if (isLoading) {
poll = setInterval(async () => {
const res = await fetch("/api/forge");
if (res.status !== 200) return;
const json: {
gameVersions: ModrinthGameVersion[];
} = await res.json();
setGame(json.gameVersions);
setIsLoading(false);
}, 500);
}
return () => clearInterval(poll);
}, [isLoading]);
return isLoading ? <Loader /> : (
<form action="/api/forge" method="POST">
<div class="grid grid-cols-3 gap-8">
<div>
<label class="block" htmlFor="game">Game Version</label>
<select name="game">
{game.filter((g) => includeSnapshots || g.major).map((g) => (
<option>{g.version}</option>
))}
</select>
<br />
<label>
<input
type="checkbox"
checked={includeSnapshots}
onChange={() => setIncludeSnapshots(!includeSnapshots)}
/>{" "}
Include Snapshots?
</label>
</div>
</div>
<div class="w-full">
<Button
class="ml-auto text-right text-lg font-pixel block mt-8"
type="submit"
>
Let's Go!
</Button>
</div>
</form>
);
}

View File

@ -57,6 +57,13 @@ export function StatusManager(
>
Restart
</Button>
<Button
color="grape"
disabled={!status}
onClick={() => sendCommand(ManageAction.kill)}
>
Kill
</Button>
</div>
</div>
);

View File

@ -74,6 +74,13 @@ export type ModrinthProject = {
monetization_status: string;
};
export type ModrinthGameVersion = {
version: string;
version_type: string;
data: string;
major: boolean;
}
export class Modrinth {
static apiRoot = "https://api.modrinth.com/v2";
@ -109,4 +116,9 @@ export class Modrinth {
const res = await fetch(this.apiRoot + "/project/" + id);
return await res.json() as ModrinthProject;
}
static async getGameVersions() {
const res = await fetch(this.apiRoot + '/tag/game_version');
return await res.json() as ModrinthGameVersion[];
}
}

View File

@ -0,0 +1,43 @@
import { Handler, Handlers } from "$fresh/server.ts";
import { SERVER_STATE } from "../../../state/serverState.ts";
import { downloadFile } from "../../../util/download.ts";
export const handler: Handlers = {
async GET(_req, _ctx) {
const gameVersions = JSON.parse(
await Deno.readTextFile("./fabric/versions/game.json"),
);
const installerVersions = JSON.parse(
await Deno.readTextFile("./fabric/versions/installer.json"),
);
const loaderVersions = JSON.parse(
await Deno.readTextFile("./fabric/versions/loader.json"),
);
return new Response(JSON.stringify({
gameVersions,
installerVersions,
loaderVersions,
}));
},
async POST(req, _ctx) {
try {
const data = await req.formData();
const game = data.get("game");
const installer = data.get("installer");
const loader = data.get("loader");
await downloadFile(`https://meta.fabricmc.net/v2/versions/loader/${game}/${loader}/${installer}/server/jar`, './server/server.jar')
SERVER_STATE.serverType = 'fabric';
SERVER_STATE.startMCServer();
const url = new URL(req.url);
return Response.redirect(url.origin + "/setup/eula", 303);
} catch (e) {
console.log(e)
return new Response("Something bad happened", { status: 500 });
}
},
};

78
routes/api/forge/index.ts Normal file
View File

@ -0,0 +1,78 @@
import { Handlers } from "$fresh/server.ts";
import { SERVER_STATE } from "../../../state/serverState.ts";
import { downloadFile } from "../../../util/download.ts";
import { getForgeDownload } from "../../../util/forge.ts";
import { getGameVersions } from "../../../util/gameVersions.ts";
export const handler: Handlers = {
async GET(_req, _ctx) {
const gameVersions = await getGameVersions();
return new Response(JSON.stringify({
gameVersions,
}));
},
async POST(req, _ctx) {
try {
const data = await req.formData();
// TODO: update for instances
await downloadFile(
await getForgeDownload(data.get("game") as string || "1.20.1"),
"./server/installer.jar",
);
const installer = new Deno.Command("java", {
args: [
"-Xmx2G",
"-jar",
"./installer.jar",
"--installServer",
],
stderr: "piped",
stdout: "piped",
cwd: "./server",
});
// const process = installer.spawn();
// process.stderr.pipeTo(Deno.stderr.writable);
// process.stdout.pipeTo(Deno.stdout.writable);
const { success } = await installer.output();
if (!success) throw "failed to install forge server";
const argFile = "./server/user_jvm_args.txt";
const jvmArgs = await Deno.readTextFile(argFile);
const memArgRx = /^(#\s)?(-Xmx)(.+)$/m;
await Deno.writeTextFile(
argFile,
jvmArgs.replace(
memArgRx,
jvmArgs.match(memArgRx)?.at(0)?.replace(/#\s?/, "") || "-Xmx4G",
),
);
const runFiles = ["./server/run.sh", "./server/run.bat"];
for (const runFile of runFiles) {
const file = (await Deno.readTextFile(runFile))
.replace("_args.txt", (e) => e + " nogui");
await Deno.writeTextFile(runFile, file);
}
SERVER_STATE.serverType = "forge";
await SERVER_STATE.startMCServer();
const url = new URL(req.url);
return Response.redirect(url.origin + "/setup/eula", 303);
// return Response.redirect(url.origin + "/terminal", 303);
} catch (e) {
console.log(e);
return new Response("Something bad happened", { status: 500 });
}
},
};

View File

@ -5,6 +5,7 @@ export enum ManageAction {
start = "start",
stop = "stop",
restart = "restart",
kill="kill"
}
export const handler: Handlers = {
@ -17,6 +18,9 @@ export const handler: Handlers = {
case ManageAction.stop:
SERVER_STATE.gracefullyStopMCServer();
return new Response("stopped");
case ManageAction.kill:
SERVER_STATE.forceStopMCServer();
return new Response("stopped");
case ManageAction.restart:
SERVER_STATE.restartMCServer();
return new Response("restarted");

View File

@ -40,27 +40,38 @@ export const handler: Handlers = {
return Response.redirect(req.url);
},
async GET(_, ctx) {
const activeMods: string[] = [];
const disabledMods: string[] = [];
if (
SERVER_STATE.serverType !== "unset" &&
SERVER_STATE.serverType !== "vanilla"
) {
for await (const fileEntry of Deno.readDir("./server/mods")) {
if (fileEntry.isFile) {
activeMods.push(fileEntry.name);
}
}
await ensureDir("./server/disabled-mods");
for await (const fileEntry of Deno.readDir("./server/disabled-mods")) {
if (fileEntry.isFile) {
disabledMods.push(fileEntry.name);
}
}
}
return ctx.render({
activeMods,
disabledMods,
});
},
};
export default async function ModsFolder({ url }: PageProps) {
const activeMods: string[] = [];
const disabledMods: string[] = [];
if (
SERVER_STATE.serverType !== "unset" && SERVER_STATE.serverType !== "vanilla"
) {
for await (const fileEntry of Deno.readDir("./server/mods")) {
if (fileEntry.isFile) {
activeMods.push(fileEntry.name);
}
}
ensureDir("./server/disabled-mods");
for await (const fileEntry of Deno.readDir("./server/disabled-mods")) {
if (fileEntry.isFile) {
disabledMods.push(fileEntry.name);
}
}
}
export default function ModsFolder(
{ url, data: { activeMods, disabledMods } }: PageProps<
{ activeMods: string[]; disabledMods: string[] }
>,
) {
return (
<div className="container p-8 flex flex-col gap-8">
<Content>

14
routes/setup/forge.tsx Normal file
View File

@ -0,0 +1,14 @@
import { Content } from "../../components/Content.tsx";
import { ForgeVersions } from "../../islands/forgeVersions.tsx";
export default function ForgeSetup() {
return (
<div class="container p-8">
<Content>
<h2 class="font-pixel text-2xl">Forge Setup</h2>
<p>Select the game version you wish to create a server for.</p>
<ForgeVersions />
</Content>
</div>
);
}

36
serverConfigs/start.ts Normal file
View File

@ -0,0 +1,36 @@
import { Loader } from "../types/mcgrizzconf.ts";
export const getServerStartCommands = (
loader: Loader,
instance = "server",
): Deno.Command => {
switch (loader) {
case "forge":
return new Deno.Command(
Deno.build.os === "windows" ? "./run.bat" : "./run.sh",
// "pwd",
{
args: [
"nogui",
],
stdin: "piped",
stdout: "piped",
cwd: "./" + instance,
},
);
case "vanilla":
case "unset":
case "fabric":
return new Deno.Command("java", {
args: [
"-Xmx8G",
"-jar",
"./server.jar",
"nogui",
],
cwd: "./" + instance,
stdin: "piped",
stdout: "piped",
});
}
};

View File

@ -3,15 +3,26 @@ import { acceptEULA, checkEULA } from "../util/EULA.ts";
import { Loader } from "../types/mcgrizzconf.ts";
import { getConfFile, updateConfFile } from "../util/confFile.ts";
import { IS_BROWSER } from "$fresh/runtime.ts";
import { getServerStartCommands } from "../serverConfigs/start.ts";
type MCServerEvent = "message";
type MCServerEventCallback = (msg: string) => void;
type status = "running" | "stopped";
class ServerState {
private _status: "running" | "stopped" = "stopped";
private _status: status = "stopped";
public get status() {
return this._status;
}
private set status(s: status) {
this._status = s;
const statusEvent = new CustomEvent("serverstatuschange", {
detail: this._status,
});
globalThis.dispatchEvent(statusEvent);
}
private command!: Deno.Command;
private process!: Deno.ChildProcess;
@ -48,7 +59,7 @@ class ServerState {
constructor() {
this._channelId = crypto.randomUUID();
const conf = getConfFile();
this._serverType = conf.loader;
this._serverVersion = conf.version;
@ -68,7 +79,7 @@ class ServerState {
1;
}
} else {
console.log(msg)
console.log(msg);
this.sendStdIn(msg);
}
});
@ -89,102 +100,78 @@ class ServerState {
}
// "instance" should be moved to a private member once multi-instance support is implemented
public startMCServer(instance = "server") {
this.command = new Deno.Command("java", {
args: [
"-Xmx2G",
"-jar",
"./server.jar",
"nogui",
],
cwd: "./" + instance,
stdin: "piped",
stdout: "piped",
});
public async startMCServer(instance = "server") {
this.command = getServerStartCommands(this._serverType, instance);
this.channel?.send("clear");
this.channel?.send('clear');
this.process = this.command.spawn();
const { readable, writable } = new TransformStream();
readable.pipeTo(this.process.stdin);
this.stdin = writable.getWriter();
this._status = "running";
const statusEvent = new CustomEvent('serverstatuschange', {detail: this._status});
globalThis.dispatchEvent(statusEvent);
this.status = "running";
this.startStream();
// this.process.status.then(() => {
// this._status = "stopped";
// });
await this.process.status;
this.status = 'stopped';
}
private async startStream() {
const stream = this.process.stdout.getReader();
const decoder = new TextDecoder();
// const stream = this.process.stdout.getReader();
// const decoder = new TextDecoder();
while (true) {
const { done, value } = await stream.read();
if (value) {
const line = decoder.decode(value);
this.channel?.send(line);
const stdoutMsg = new CustomEvent('stdoutmsg', {
detail: line
})
globalThis.dispatchEvent(stdoutMsg);
}
if (done) break;
}
// while (true) {
// const { done, value } = await stream.read();
// if (value) {
// const line = decoder.decode(value);
// this.channel?.send(line);
// const stdoutMsg = new CustomEvent("stdoutmsg", {
// detail: line,
// });
// globalThis.dispatchEvent(stdoutMsg);
// }
// if (done) break;
// }
// await this.process.stdout.pipeThrough(new TextDecoderStream()).pipeTo(
// new WritableStream({
// write: (chunk) => {
// this.channel?.send(chunk);
// const stdoutMsg = new CustomEvent("stdoutmsg", {
// detail: chunk,
// });
// globalThis.dispatchEvent(stdoutMsg);
// },
// }),
// );
await this.process.stdout.pipeThrough(new TextDecoderStream()).pipeTo(
new WritableStream({
write: (chunk) => {
this.channel?.send(chunk);
const stdoutMsg = new CustomEvent("stdoutmsg", {
detail: chunk,
});
globalThis.dispatchEvent(stdoutMsg);
},
}),
);
}
public gracefullyStopMCServer() {
this._status = "stopped";
this.status = "stopped";
this.sendStdIn("stop");
const statusEvent = new CustomEvent('serverstatuschange', {detail: this._status});
globalThis.dispatchEvent(statusEvent);
}
public forceStopMCServer() {
this._status = "stopped";
this.status = "stopped";
this.process.kill();
const statusEvent = new CustomEvent('serverstatuschange', {detail: this._status});
globalThis.dispatchEvent(statusEvent);
}
public async restartMCServer() {
if (this.status === "running") {
await this.sendStdIn("stop");
const statusEvent = new CustomEvent('serverstatuschange', {detail: 'restarting'});
const statusEvent = new CustomEvent("serverstatuschange", {
detail: "restarting",
});
globalThis.dispatchEvent(statusEvent);
// while (true) {
await this.process.status;
// }
}
const statusEvent = new CustomEvent('serverstatuschange', {detail: this._status});
globalThis.dispatchEvent(statusEvent);
this.startMCServer();
}

View File

@ -1,35 +1,41 @@
import { ensureFile } from "$std/fs/ensure_file.ts";
/**
*
* @param src url of file
* @param dest destination file. If `useFileName` is true, this should be the destination directory
* @param [useFileName] whether to use the inferred file name from `src`
*/
export async function downloadFile(src: string, dest: string, useFileName?:boolean) {
export async function downloadFile(
src: string,
dest: string,
useFileName?: boolean,
) {
if (!(src.startsWith("http://") || src.startsWith("https://"))) {
throw new TypeError("URL must start with be http:// or https://");
}
const fileName = src.split('/').at(-1);
const resp = await fetch(src);
if (!resp.ok) {
const fileName = src.split("/").at(-1);
const res = await fetch(src);
if (!res.ok) {
throw new Deno.errors.BadResource(
`Request failed with status ${resp.status}`,
`Request failed with status ${res.status}`,
);
} else if (!resp.body) {
} else if (!res.body) {
throw new Deno.errors.UnexpectedEof(
`The download url ${src} doesn't contain a file to download`,
);
} else if (resp.status === 404) {
} else if (res.status === 404) {
throw new Deno.errors.NotFound(
`The requested url "${src}" could not be found`,
);
}
const blob = await res.blob();
const buffer = await blob.arrayBuffer();
const uint8array = new Uint8Array(buffer);
await ensureFile(useFileName ? dest + fileName : dest);
const file = await Deno.open(dest, { truncate: true, write: true });
resp.body.pipeTo(file.writable);
}
await Deno.writeFile(dest, uint8array);
}

15
util/forge.ts Normal file
View File

@ -0,0 +1,15 @@
export const getForgeDownload = async (version: string, latest?: boolean) => {
const res = await fetch(
`https://files.minecraftforge.net/net/minecraftforge/forge/promotions_slim.json`,
);
const { promos } = await res.json();
// https://maven.minecraftforge.net/net/minecraftforge/forge/1.20.1-47.2.1/forge-1.20.1-47.2.1-installer.jar
let loaderVersion = promos[`${version}-${latest ? "latest" : "recommended"}`];
if (!loaderVersion) loaderVersion = promos[`${version}-latest`];
return `https://maven.minecraftforge.net/net/minecraftforge/forge/${version}-${loaderVersion}/forge-${version}-${loaderVersion}-installer.jar`;
};

18
util/gameVersions.ts Normal file
View File

@ -0,0 +1,18 @@
import { ensureFile } from "$std/fs/ensure_file.ts";
import { Modrinth, ModrinthGameVersion } from "../lib/modrinth.ts";
export const getGameVersions = async (releaseOnly?: boolean) => {
const cacheFile = "./cache/gameVersions.json";
await ensureFile(cacheFile);
let versions: ModrinthGameVersion[] = JSON.parse(
await Deno.readTextFile(cacheFile) || "[]",
);
if (!versions.length) {
versions = await Modrinth.getGameVersions();
await Deno.writeTextFile(cacheFile, JSON.stringify(versions));
}
return versions.filter(v => !releaseOnly || v.major);
};