commit 4ae058246426e1a6a833887400277747f4f57328 Author: WeeXnes Date: Sat Mar 1 11:59:31 2025 +0100 initial commit diff --git a/core/globals.ts b/core/globals.ts new file mode 100644 index 0000000..7e9f2c2 --- /dev/null +++ b/core/globals.ts @@ -0,0 +1,21 @@ +import type {MinecraftServer} from "~/types/MinecraftServer"; +import type {SettingsJsonFile} from "~/types/SettingsJsonFile"; +import {saveJsonFile} from "~/util/jsonLoader"; + +export namespace environment{ + export namespace paths{ + export let data: string = "/home/weexnes/.mcservermanager"; + export let servers: string = "/home/weexnes/.mcservermanager/servers"; + } + + + export namespace files{ + export let settings: string = paths.data + "/settings.json"; + } + + + export let settings: SettingsJsonFile; +} + + + diff --git a/pages/index.vue b/pages/index.vue new file mode 100644 index 0000000..e75050d --- /dev/null +++ b/pages/index.vue @@ -0,0 +1,232 @@ + + + + + + + + + \ No newline at end of file diff --git a/server/api/getServers.ts b/server/api/getServers.ts new file mode 100644 index 0000000..de1fb8a --- /dev/null +++ b/server/api/getServers.ts @@ -0,0 +1,10 @@ +import { defineEventHandler, getCookie, createError } from 'h3'; +import {environment} from "~/core/globals"; + +export default defineEventHandler(async (event) => { + try { + return environment.settings.servers; + } catch (error) { + console.error('Error fetching CPU info:', error); + } +}); diff --git a/server/api/setServers.ts b/server/api/setServers.ts new file mode 100644 index 0000000..c65b33b --- /dev/null +++ b/server/api/setServers.ts @@ -0,0 +1,18 @@ +import {environment} from "~/core/globals"; +import {saveJsonFile} from "~/util/jsonLoader"; + +export default defineEventHandler(async (event) => { + const body = await readBody(event); + const { serverList } = body; + + try { + console.log("Recived server list"); + environment.settings.servers = serverList; + saveJsonFile() + + return { status: 'success' }; + } catch (error) { + return { status: 'error', error: error }; + } +}); + diff --git a/server/api/startServer.ts b/server/api/startServer.ts new file mode 100644 index 0000000..c42077e --- /dev/null +++ b/server/api/startServer.ts @@ -0,0 +1,44 @@ +import {environment} from "~/core/globals"; +import {saveJsonFile} from "~/util/jsonLoader"; +import {MinecraftServer} from "~/types/MinecraftServer"; +import {execa} from "execa"; + + +export default defineEventHandler(async (event) => { + const body = await readBody(event); + const server_name: string = body.name + + const server = environment.settings.servers.find(server => server.name == server_name); + + if(!server) { + return { message: "Server with name " + server_name + " does not exist" }; + } + + const workingDir = environment.paths.servers + "/" + server.name; + const jarPath = environment.paths.servers + "/" + server.name + "/server.jar"; + + try { + server.process = execa('java', ['-jar', jarPath, 'nogui'], { + cwd: workingDir, + }); + + server.process.stdout.on('data', (data: string) => { + const logData = data.toString(); + console.log(logData); + }); + + server.process.stderr.on('data', (data: string) => { + const errorData = data.toString(); + console.log(errorData); + }); + + server.process.on('exit', (code: string) => { + console.log(`Minecraft server process exited with code ${code}`); + server.process = null; + }); + + return { message: "Minecraft server started." }; + } catch (error: any) { + return { message: "Failed to start Minecraft server.", error: error.message }; + } +}); diff --git a/server/plugins/init.ts b/server/plugins/init.ts new file mode 100644 index 0000000..db520fd --- /dev/null +++ b/server/plugins/init.ts @@ -0,0 +1,16 @@ +import * as fs from 'fs'; +import * as path from 'path'; +import {environment} from "~/core/globals"; +import {loadJsonFile, removeServerByName, saveJsonFile, createPathIfNotExists} from "~/util/jsonLoader"; + +export default defineNitroPlugin((nitroApp) => { + console.log("Loading config...") + for (const key of Object.keys(environment.paths)) { + createPathIfNotExists(environment.paths[key as keyof typeof environment.paths]); + } + loadJsonFile() +}); + + + + diff --git a/tailwind.config.js b/tailwind.config.js new file mode 100644 index 0000000..94d45dc --- /dev/null +++ b/tailwind.config.js @@ -0,0 +1,3 @@ +module.exports = { + plugins: [require('daisyui')], +}; \ No newline at end of file diff --git a/types/MinecraftServer.ts b/types/MinecraftServer.ts new file mode 100644 index 0000000..423143f --- /dev/null +++ b/types/MinecraftServer.ts @@ -0,0 +1,27 @@ +import type {ResultPromise} from "execa"; + +export interface MinecraftServer { + name: string; + port: number; + maxPlayers: number; + version: string; + jar_url: string; + + isRunning: boolean; + currentPlayers: number; + + + difficulty: "peaceful" | "easy" | "normal" | "hard"; + spawnProtection: number; + viewDistance: number; + + + minMemory: number; + maxMemory: number; + + logs: string[]; + + + process: any; + +} diff --git a/types/SettingsJsonFile.ts b/types/SettingsJsonFile.ts new file mode 100644 index 0000000..ce979b4 --- /dev/null +++ b/types/SettingsJsonFile.ts @@ -0,0 +1,6 @@ +import type {MinecraftServer} from "~/types/MinecraftServer"; + +export interface SettingsJsonFile { + eula: boolean; + servers: MinecraftServer[]; +} diff --git a/util/jsonLoader.ts b/util/jsonLoader.ts new file mode 100644 index 0000000..6c85687 --- /dev/null +++ b/util/jsonLoader.ts @@ -0,0 +1,112 @@ +import {environment} from "~/core/globals"; +import * as fs from 'fs'; +import * as path from 'path'; +import type {SettingsJsonFile} from "~/types/SettingsJsonFile"; +import * as https from "node:https"; + +export function loadJsonFile(){ + try { + console.log(environment.files.settings) + createEmptySettingsIfNotExists() + let jsonStr = fs.readFileSync(environment.files.settings, 'utf-8') + environment.settings = JSON.parse(jsonStr); + + checkAllServerDirectories() + + + + + + } catch (error) { + console.error('Error reading or parsing JSON file:', error); + } +} + + +export function saveJsonFile() { + const jsonSettings = JSON.stringify(environment.settings, null, 2); + fs.writeFileSync(environment.files.settings, jsonSettings); + console.log(`Settings saved to ` + environment.files.settings); +} + + + +export function removeServerByName(name: string) { + const index = environment.settings.servers.findIndex(item => item.name === name); + environment.settings.servers.splice(index, 1); + console.log("Removed server \"" + name + "\" at index " + index); +} + + +function createEmptySettingsIfNotExists() { + try { + fs.accessSync(environment.files.settings); + console.log('Settings already exists!'); + } catch (error) { + console.log('Settings does not exist, creating an empty Settings-file...'); + let emptySettings: SettingsJsonFile = ({ + eula: false, + servers:[] + }); + const jsonSettings = JSON.stringify(emptySettings, null, 2); + fs.writeFileSync(environment.files.settings, jsonSettings); + console.log('File created successfully and is empty!'); + } +} + + +export function createPathIfNotExists(dirPath: string) { + try { + if (!fs.existsSync(dirPath)) { + fs.mkdirSync(dirPath, { recursive: true }); // Create the directory (and parent directories if necessary) + console.log(`Directory created at ${dirPath}`); + } + } catch (err) { + console.error('Error creating directory:', err); + } +} + + +function checkAllServerDirectories(){ + environment.settings.servers.forEach(server => { + createPathIfNotExists(environment.paths.servers + "/" + server.name) + }) + + environment.settings.servers.forEach(server => { + const destinationPath = environment.paths.servers + "/" + server.name + "/server.jar" + try { + fs.accessSync(destinationPath); + console.log('Settings already exists!'); + } catch (error) { + downloadFile(server.jar_url, destinationPath); + } + }) +} + + +function downloadFile(url: string, dest: string) { + if(url == "") + return; + + + console.log(dest + ' doesnt exist, downloading now from ' + url); + const file = fs.createWriteStream(dest); + + https.get(url, (response) => { + if (response.statusCode === 200) { + response.pipe(file); + } else { + console.error(`Failed to download file. Status Code: ${response.statusCode}`); + } + + file.on('finish', () => { + file.close(); + console.log('Download complete!'); + }); + }).on('error', (err) => { + // Handle any errors during the download + console.error('Error during download:', err.message); + fs.unlink(dest, () => {}); + }); +} +