Skip to content

Commit

Permalink
feat(MainWindow): show instances
Browse files Browse the repository at this point in the history
  • Loading branch information
ariscript committed Nov 26, 2021
1 parent 5dc2258 commit 25aa16c
Show file tree
Hide file tree
Showing 17 changed files with 167 additions and 34 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
![MultiServer](assets/banner.jpg)
![MultiServer](img/banner.jpg)

> The most pragmatic and efficient way to orchestrate multiple Minecraft servers.
File renamed without changes
Binary file added img/fabric_logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/paper_logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/vanilla_logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"packagerConfig": {
"extraResource": [
"./resources/server.properties",
"./resources/fabric-installer-0.9.0.jar"
"./resources/fabric-installer.jar"
]
},
"makers": [
Expand Down Expand Up @@ -94,10 +94,12 @@
"electron": "16.0.1",
"eslint": "^7.6.0",
"eslint-plugin-import": "^2.20.0",
"file-loader": "^6.2.0",
"fork-ts-checker-webpack-plugin": "^6.0.1",
"node-loader": "^2.0.0",
"postcss": "^8.3.11",
"postcss-loader": "^6.2.0",
"prettier": "^2.5.0",
"style-loader": "^3.0.0",
"tailwindcss": "^2.2.19",
"ts-loader": "^9.2.2",
Expand All @@ -109,6 +111,7 @@
"node-fetch": "^3.1.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"sanitize-filename": "^1.6.3",
"update-electron-app": "^2.0.1"
}
}
27 changes: 27 additions & 0 deletions src/components/Instance.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React from "react";
import { InstanceOptions } from "../types";

import fabricLogo from "../../img/fabric_logo.png";
import paperLogo from "../../img/paper_logo.png";
import vanillaLogo from "../../img/vanilla_logo.png";

const images = {
fabric: fabricLogo,
paper: paperLogo,
vanilla: vanillaLogo,
} as const;

interface InstanceProps {
info: InstanceOptions;
}

const Instance = ({ info }: InstanceProps): JSX.Element => {
return (
<div className="rounded-md border-2 border-gray-800 p-1 m-2 flex flex-col justify-center items-center">
<img src={images[info.type]} width={64} />
<p>{info.name}</p>
</div>
);
};

export default Instance;
4 changes: 4 additions & 0 deletions src/global.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import type { IpcChannels } from "./types";

declare global {
declare module "*.png" {
const src: string;
export default src;
}
interface Window {
ipc: IpcChannels;
log: import("electron-log").LogFunctions;
Expand Down
11 changes: 8 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import updater from "update-electron-app";
import log from "electron-log";

import createInstance from "./lib/instances/createInstance";
import { getInstances } from "./lib/instances/getInstances";

// declarations for webpack magic constants for built react code
declare const MAIN_WINDOW_WEBPACK_ENTRY: string;
Expand All @@ -19,9 +20,11 @@ if (require("electron-squirrel-startup")) {

updater();

const createWindow = (): void => {
let mainWindow: BrowserWindow;

const createWindow = () => {
// Create the browser window.
const mainWindow = new BrowserWindow({
mainWindow = new BrowserWindow({
height: 600,
width: 800,
webPreferences: {
Expand Down Expand Up @@ -72,8 +75,10 @@ ipcMain.on("newInstanceWindow", () => {

ipcMain.on("closeWindow", (e) => {
const sender = BrowserWindow.fromWebContents(e.sender);
log.debug(sender);
sender?.close();
});

ipcMain.handle("createInstance", createInstance);
ipcMain.handle("getInstances", getInstances);

export const getMainWindow = (): BrowserWindow => mainWindow;
9 changes: 9 additions & 0 deletions src/lib/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { app } from "electron";

import path from "path";

export const resourcesPath = app.isPackaged
? process.resourcesPath
: path.join(process.cwd(), "resources");

export const instancesPath = path.join(app.getPath("userData"), "instances");
34 changes: 20 additions & 14 deletions src/lib/instances/createInstance.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import { app, IpcMainInvokeEvent } from "electron";
import type { IpcMainInvokeEvent } from "electron";
import fetch from "node-fetch";
import log from "electron-log";
import sanitize from "sanitize-filename";

import https from "https";
import fs from "fs/promises";
import { createWriteStream } from "fs";
import path from "path";
import cp from "child_process";

import { getMainWindow } from "../../index";
import { instancesPath, resourcesPath } from "../constants";
import type { InstanceOptions } from "../../types";

/**
Expand All @@ -19,17 +22,20 @@ export default async function create(
_event: IpcMainInvokeEvent,
opts: InstanceOptions
): Promise<boolean> {
const instanceRoot = path.join(
app.getPath("userData"),
"instances",
opts.name
);
try {
const sanitizedName = sanitize(
opts.name.toLowerCase().replace(/\s/g, "_")
);

const resourcesPath = app.isPackaged
? process.resourcesPath
: path.join(process.cwd(), "resources");
if (sanitizedName === "") {
log.error(`Invalid instance name ${opts.name}`);
throw new Error(`Invalid instance name ${opts.name}`);
}

const instanceRoot = path.join(instancesPath, sanitizedName);

// TODO: check if instance already exists

try {
log.info(
`Creating directory for ${opts.type} server instance ${opts.name}`
);
Expand All @@ -38,7 +44,7 @@ export default async function create(
log.silly("Writing configuration file");
await fs.writeFile(
path.join(instanceRoot, "multiserver.config.json"),
JSON.stringify(opts, (v) => v, 4)
JSON.stringify(opts, undefined, 4)
);

log.silly("Writing eula.txt");
Expand All @@ -50,9 +56,6 @@ export default async function create(
path.join(instanceRoot, "server.properties")
);

// TODO: check if instance already exists
// TODO: fabric

if (opts.type === "fabric") {
log.debug("Calling fabric installer");

Expand Down Expand Up @@ -122,6 +125,9 @@ export default async function create(
} catch (e) {
log.error(e);
return false;
} finally {
// way less work than having to wire up an IPC event to let the main window know that theres an new instance
setTimeout(() => getMainWindow().reload(), 500);
}
}

Expand Down
23 changes: 23 additions & 0 deletions src/lib/instances/getInstances.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import fs from "fs/promises";
import path from "path";

import type { InstanceOptions, InstanceInfo } from "../../types";
import { instancesPath } from "../constants";

export async function getInstances(): Promise<InstanceInfo[]> {
const instances = await fs.readdir(instancesPath);

return Promise.all(
instances.map(async (instance) => {
const conf = await fs.readFile(
path.join(instancesPath, instance, "multiserver.config.json"),
"utf8"
);

return {
path: path.join(instancesPath, instance),
info: JSON.parse(conf) as InstanceOptions,
};
})
);
}
1 change: 1 addition & 0 deletions src/preload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ contextBridge.exposeInMainWorld("ipc", {
newInstanceWindow: () => ipcRenderer.send("newInstanceWindow"),
createInstance: (opts) => ipcRenderer.invoke("createInstance", opts),
closeWindow: () => ipcRenderer.send("closeWindow"),
getInstances: () => ipcRenderer.invoke("getInstances"),
} as IpcChannels);

contextBridge.exposeInMainWorld("log", log.functions);
17 changes: 7 additions & 10 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
export interface InstanceOptions {
name: string;
type:
| "vanilla"
| "spigot"
| "bukkit"
| "paper"
| "fabric"
| "purpur"
| "tuinity"
| "fabric";

type: "vanilla" | "paper" | "fabric";
version: string;
javaPath?: string;
jvmArgs?: string;
}

export interface InstanceInfo {
path: string;
info: InstanceOptions;
}

export type IpcChannels = {
newInstanceWindow: () => void;
createInstance: (opts: InstanceOptions) => Promise<boolean>;
closeWindow: () => void;
getInstances: () => Promise<InstanceInfo[]>;
};
27 changes: 23 additions & 4 deletions src/windows/MainWIndow.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,36 @@
import React from "react";
import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
import "tailwindcss/tailwind.css";
import type { InstanceInfo } from "../types";

import "../app.global.css";
import Instance from "../components/Instance";

const MainWindow = () => {
const [instances, setInstances] = useState<InstanceInfo[]>([]);

useEffect(() => {
const fetchInstances = () =>
void ipc
.getInstances()
.then(setInstances)
.catch((err) => log.error(err));

fetchInstances();
}, []);

return (
<div>
<h1>Welcome to MultiServer</h1>
{/* TODO: add instances view */}

<div className="grid grid-cols-3">
{instances.map((instance) => (
<Instance info={instance.info} />
))}
</div>

<button
onClick={ipc.newInstanceWindow}
className="rounded-md text-black bg-green-500 hover:bg-green-600 focus:bg-green-700 p-1 focus:text-white border-2 border-black transition-colors"
className="rounded-md text-black bg-green-500 hover:bg-green-600 focus:bg-green-700 p-2 focus:text-white border-2 border-black transition-colors"
>
New Instance
</button>
Expand Down
7 changes: 7 additions & 0 deletions webpack.rules.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,11 @@ module.exports = [
},
],
},
{
test: /\.(png|jpe?g|gif|jp2|webp)$/,
loader: "file-loader",
options: {
name: "[name].[ext]",
},
},
];
34 changes: 33 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2749,6 +2749,14 @@ file-entry-cache@^6.0.1:
dependencies:
flat-cache "^3.0.4"

file-loader@^6.2.0:
version "6.2.0"
resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-6.2.0.tgz#baef7cf8e1840df325e4390b4484879480eebe4d"
integrity sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==
dependencies:
loader-utils "^2.0.0"
schema-utils "^3.0.0"

filename-reserved-regex@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz#abf73dfab735d045440abfea2d91f389ebbfa229"
Expand Down Expand Up @@ -5243,6 +5251,11 @@ prepend-http@^2.0.0:
resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897"
integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=

prettier@^2.5.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.5.0.tgz#a6370e2d4594e093270419d9cc47f7670488f893"
integrity sha512-FM/zAKgWTxj40rH03VxzIPdXmj39SwSjwG0heUcNFwI+EMZJnY93yAiKXM3dObIKAM5TA88werc8T/EwhB45eg==

pretty-bytes@^1.0.2:
version "1.0.4"
resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-1.0.4.tgz#0a22e8210609ad35542f8c8d5d2159aff0751c84"
Expand Down Expand Up @@ -5747,6 +5760,13 @@ safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.2,
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==

sanitize-filename@^1.6.3:
version "1.6.3"
resolved "https://registry.yarnpkg.com/sanitize-filename/-/sanitize-filename-1.6.3.tgz#755ebd752045931977e30b2025d340d7c9090378"
integrity sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==
dependencies:
truncate-utf8-bytes "^1.0.0"

scheduler@^0.20.2:
version "0.20.2"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91"
Expand All @@ -5764,7 +5784,7 @@ schema-utils@2.7.0:
ajv "^6.12.2"
ajv-keywords "^3.4.1"

schema-utils@^3.1.0, schema-utils@^3.1.1:
schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281"
integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==
Expand Down Expand Up @@ -6469,6 +6489,13 @@ trim-repeated@^1.0.0:
dependencies:
escape-string-regexp "^1.0.2"

truncate-utf8-bytes@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz#405923909592d56f78a5818434b0b78489ca5f2b"
integrity sha1-QFkjkJWS1W94pYGENLC3hInKXys=
dependencies:
utf8-byte-length "^1.0.1"

ts-loader@^9.2.2:
version "9.2.6"
resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.2.6.tgz#9937c4dd0a1e3dbbb5e433f8102a6601c6615d74"
Expand Down Expand Up @@ -6647,6 +6674,11 @@ username@^5.1.0:
execa "^1.0.0"
mem "^4.3.0"

utf8-byte-length@^1.0.1:
version "1.0.4"
resolved "https://registry.yarnpkg.com/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz#f45f150c4c66eee968186505ab93fcbb8ad6bf61"
integrity sha1-9F8VDExm7uloGGUFq5P8u4rWv2E=

util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
Expand Down

0 comments on commit 25aa16c

Please # to comment.