working prototype
This commit is contained in:
parent
2e55a6d566
commit
abdf5ddefc
10 changed files with 317 additions and 71 deletions
|
@ -14,10 +14,13 @@
|
|||
"@nuxtjs/tailwindcss": "^6.13.1",
|
||||
"axios": "^1.7.9",
|
||||
"daisyui": "^4.12.23",
|
||||
"execa": "^9.5.2",
|
||||
"ini": "^5.0.0",
|
||||
"nuxt": "^3.15.4",
|
||||
"vue": "latest",
|
||||
"vue-router": "latest",
|
||||
"execa": "^9.5.2",
|
||||
"ini": "^5.0.0"
|
||||
"vue-router": "latest"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/ini": "^4.1.1"
|
||||
}
|
||||
}
|
||||
|
|
224
pages/index.vue
224
pages/index.vue
|
@ -3,18 +3,20 @@
|
|||
<h1 class="text-4xl font-bold text-center mb-6">Minecraft Servers</h1>
|
||||
<div class="grid md:grid-cols-3 gap-6 w-full max-w-5xl mb-8">
|
||||
<div v-for="server in settings.servers" class="card bg-base-100 shadow-2xl p-6">
|
||||
<h2 class="text-xl font-bold text-center cursor-pointer" @click="editServerDialog(server)">
|
||||
<h2 class="text-xl font-bold text-center cursor-pointer" @click="showServerLogDialog(server)">
|
||||
{{ server.name }}
|
||||
</h2>
|
||||
|
||||
<div class="mt-2 text-sm">
|
||||
<p><strong>Version:</strong> {{ server.version }}</p>
|
||||
<p><strong>Port</strong> {{ server.port }}</p>
|
||||
<p><strong>Memory:</strong> {{ server.minMemory }}-{{ server.maxMemory }}GB</p>
|
||||
<p><strong>Memory:</strong> {{ server.maxMemory }}GB</p>
|
||||
</div>
|
||||
|
||||
<div class="form-control mt-4 flex flex-row gap-2">
|
||||
<button @click="startServer(server)" class="btn btn-primary w-1/2">Start</button>
|
||||
<button @click="stopServer(server)" class="btn btn-error w-1/2">Stop</button>
|
||||
<button @click="startServer(server)" class="btn btn-primary w-1/3">Start</button>
|
||||
<button @click="showEditServerDialog(server)" class="btn btn-warning w-1/3">Edit</button>
|
||||
<button @click="stopServer(server)" class="btn btn-error w-1/3">Stop</button>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
@ -40,12 +42,6 @@
|
|||
</div>
|
||||
<input v-model="addDialog.newServer.name" type="text" placeholder="Type here" class="input input-bordered w-full max-w-xs" />
|
||||
</label>
|
||||
<label class="form-control w-full max-w-xs">
|
||||
<div class="label">
|
||||
<span class="label-text">Port</span>
|
||||
</div>
|
||||
<input v-model="addDialog.newServer.port" type="text" placeholder="Type here" class="input input-bordered w-full max-w-xs" />
|
||||
</label>
|
||||
<label class="form-control w-full max-w-xs">
|
||||
<div class="label">
|
||||
<span class="label-text">Version</span>
|
||||
|
@ -59,15 +55,6 @@
|
|||
<input v-model="addDialog.newServer.jar_url" type="text" placeholder="Type here" class="input input-bordered w-full max-w-xs" />
|
||||
</label>
|
||||
|
||||
|
||||
<label class="form-control w-full max-w-xs">
|
||||
<div class="label">
|
||||
<span class="label-text">JVM Min Memory</span>
|
||||
</div>
|
||||
<input v-model="addDialog.newServer.minMemory" type="text" placeholder="Type here" class="input input-bordered w-full max-w-xs" />
|
||||
</label>
|
||||
|
||||
|
||||
<label class="form-control w-full max-w-xs">
|
||||
<div class="label">
|
||||
<span class="label-text">JVM Max Memory</span>
|
||||
|
@ -88,19 +75,96 @@
|
|||
|
||||
|
||||
|
||||
<input type="checkbox" id="editServerModal" class="modal-toggle" />
|
||||
<input type="checkbox" id="serverLogModal" class="modal-toggle" />
|
||||
<div class="modal" role="dialog">
|
||||
<div class="modal-box w-11/12 max-w-5xl">
|
||||
<h3 class="text-lg font-bold text-center">{{ editDialog.editedServer.name }}</h3>
|
||||
<h3 class="text-lg font-bold text-center">{{ serverLogDialog.selectedServer.name }}</h3>
|
||||
<div class="mockup-code w-full">
|
||||
<pre v-for="str in testrec.logs" data-prefix="$"><code>{{str}}</code></pre>
|
||||
<pre v-for="str in serverLogDialog.logs" data-prefix="$"><code>{{str}}</code></pre>
|
||||
</div>
|
||||
<div class="modal-action flex justify-between space-x-4">
|
||||
<!-- Start Button -->
|
||||
<button @click="startServer(serverLogDialog.selectedServer)" class="btn btn-primary">Start</button>
|
||||
|
||||
<!-- Stop Button -->
|
||||
<button @click="stopServer(serverLogDialog.selectedServer)" class="btn btn-error">Stop</button>
|
||||
</div>
|
||||
</div>
|
||||
<label class="modal-backdrop" for="editServerModal">Close</label>
|
||||
<label class="modal-backdrop" for="serverLogModal">Close</label>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<dialog id="editServerModal" class="modal">
|
||||
<div class="modal-box">
|
||||
<h3 class="text-lg font-bold">Edit Server: {{ editServerDialog.selectedServer.name }}</h3>
|
||||
|
||||
<div class="grid grid-cols-2 gap-4">
|
||||
<!-- First row -->
|
||||
<label class="form-control w-full max-w-xs">
|
||||
<div class="label">
|
||||
<span class="label-text">Difficulty</span>
|
||||
</div>
|
||||
<input v-model="editServerDialog.properties['difficulty']" type="text" placeholder="Type here" class="input input-bordered w-full max-w-xs" />
|
||||
</label>
|
||||
|
||||
<label class="form-control w-full max-w-xs">
|
||||
<div class="label">
|
||||
<span class="label-text">Server Port</span>
|
||||
</div>
|
||||
<input v-model="editServerDialog.properties['server-port']" type="text" placeholder="Type here" class="input input-bordered w-full max-w-xs" />
|
||||
</label>
|
||||
|
||||
<!-- Second row (adding more elements) -->
|
||||
<label class="form-control w-full max-w-xs">
|
||||
<div class="label">
|
||||
<span class="label-text">Command Blocks</span>
|
||||
</div>
|
||||
<input v-model="editServerDialog.properties['enable-command-block']" type="text" placeholder="Type here" class="input input-bordered w-full max-w-xs" />
|
||||
</label>
|
||||
|
||||
<label class="form-control w-full max-w-xs">
|
||||
<div class="label">
|
||||
<span class="label-text">Gamemode</span>
|
||||
</div>
|
||||
<input v-model="editServerDialog.properties['gamemode']" type="text" placeholder="Type here" class="input input-bordered w-full max-w-xs" />
|
||||
</label>
|
||||
|
||||
<!-- Third row -->
|
||||
<label class="form-control w-full max-w-xs">
|
||||
<div class="label">
|
||||
<span class="label-text">Slots</span>
|
||||
</div>
|
||||
<input v-model="editServerDialog.properties['max-players']" type="text" placeholder="Type here" class="input input-bordered w-full max-w-xs" />
|
||||
</label>
|
||||
|
||||
<label class="form-control w-full max-w-xs">
|
||||
<div class="label">
|
||||
<span class="label-text">PVP</span>
|
||||
</div>
|
||||
<input v-model="editServerDialog.properties['pvp']" type="text" placeholder="Type here" class="input input-bordered w-full max-w-xs" />
|
||||
</label>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="modal-action flex justify-between space-x-4">
|
||||
<!-- Save Button -->
|
||||
<form method="dialog">
|
||||
<button class="btn btn-primary" @click="editServer">Save</button>
|
||||
</form>
|
||||
|
||||
<!-- Delete Button -->
|
||||
<form method="dialog">
|
||||
<button class="btn btn-error" @click="deleteServer(editServerDialog)">Delete</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</dialog>
|
||||
|
||||
|
||||
|
||||
</template>
|
||||
|
||||
|
||||
|
@ -110,11 +174,7 @@
|
|||
|
||||
import type {MinecraftServer} from "~/types/MinecraftServer";
|
||||
import axios from 'axios';
|
||||
|
||||
|
||||
const testrec = reactive({
|
||||
logs: [] as string[],
|
||||
})
|
||||
import { stringify , parse } from 'ini'
|
||||
|
||||
const settings = reactive({
|
||||
servers: [] as MinecraftServer[],
|
||||
|
@ -124,8 +184,14 @@ const addDialog = reactive({
|
|||
newServer: {} as MinecraftServer
|
||||
})
|
||||
|
||||
const editDialog = reactive({
|
||||
editedServer: {} as MinecraftServer
|
||||
const serverLogDialog = reactive({
|
||||
selectedServer: {} as MinecraftServer,
|
||||
logs: [] as string[],
|
||||
})
|
||||
|
||||
const editServerDialog = reactive({
|
||||
selectedServer: {} as MinecraftServer,
|
||||
properties: {} as { [p: string]: any }
|
||||
})
|
||||
|
||||
|
||||
|
@ -140,54 +206,111 @@ const getServers = async () => {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
const showServerLogDialog = async (server: MinecraftServer) => {
|
||||
serverLogDialog.selectedServer = server
|
||||
// @ts-ignore
|
||||
serverLogModal.checked = true
|
||||
}
|
||||
|
||||
const getLogs = async () => {
|
||||
|
||||
|
||||
// @ts-ignore
|
||||
if(!editServerModal.checked)
|
||||
if(!serverLogModal.checked){
|
||||
if(serverLogDialog.logs.length != 0){
|
||||
serverLogDialog.logs.length = 0;
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if(!serverLogDialog.selectedServer)
|
||||
return
|
||||
|
||||
try{
|
||||
const response = await axios.post('/api/getLogs', {
|
||||
name: editDialog.editedServer.name
|
||||
name: serverLogDialog.selectedServer.name
|
||||
});
|
||||
|
||||
console.log(response.data.message)
|
||||
//console.log(response)
|
||||
const strRet: string = response.data.logs;
|
||||
const strRet = response.data.logs;
|
||||
|
||||
|
||||
const stringArray = strRet.split('\n');
|
||||
//console.log(stringArray);
|
||||
testrec.logs.length = 0;
|
||||
stringArray.slice(-20).forEach(element => {
|
||||
testrec.logs.push(element);
|
||||
serverLogDialog.logs.length = 0;
|
||||
stringArray.slice(-20).forEach((element: string) => {
|
||||
serverLogDialog.logs.push(element);
|
||||
})
|
||||
}catch(error){
|
||||
console.error(`Error fetch: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const editServerDialog = async (server: MinecraftServer) => {
|
||||
editDialog.editedServer = server
|
||||
|
||||
const showEditServerDialog = async (server: MinecraftServer) => {
|
||||
editServerDialog.selectedServer = server
|
||||
await getProperties()
|
||||
// @ts-ignore
|
||||
//editServerModal.showModal()
|
||||
editServerModal.checked = true
|
||||
editServerModal.showModal()
|
||||
}
|
||||
|
||||
const getProperties = async () => {
|
||||
// @ts-ignore
|
||||
editServerModal.showModal()
|
||||
|
||||
try{
|
||||
const response = await axios.post('/api/getProperties', {
|
||||
name: editServerDialog.selectedServer.name
|
||||
});
|
||||
console.log(response.data.properties)
|
||||
|
||||
editServerDialog.properties = parse(response.data.properties)
|
||||
|
||||
}catch(error){
|
||||
console.error(`Error fetch: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const addServer = async () => {
|
||||
if (!settings.servers.some(server => server.name === addDialog.newServer.name)) {
|
||||
settings.servers.push(addDialog.newServer)
|
||||
await syncServers()
|
||||
settings.servers.push({ ...addDialog.newServer });
|
||||
await syncServers();
|
||||
}
|
||||
}
|
||||
|
||||
const deleteServer = async () => {
|
||||
let index = settings.servers.findIndex(item => item.name === editDialog.editedServer.name);
|
||||
settings.servers.splice(index, 1);
|
||||
await syncServers()
|
||||
|
||||
|
||||
const editServer = async () => {
|
||||
try {
|
||||
const response = await axios.post('/api/setProperties', {
|
||||
name: editServerDialog.selectedServer.name,
|
||||
properties: stringify(editServerDialog.properties)
|
||||
});
|
||||
console.log(response.data);
|
||||
} catch (error) {
|
||||
console.error(`Error `, error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const deleteServer = async (server: MinecraftServer) => {
|
||||
try {
|
||||
const response = await axios.post('/api/deleteServer', {
|
||||
name: server.name
|
||||
});
|
||||
console.log(response.data);
|
||||
await getServers()
|
||||
} catch (error) {
|
||||
console.error(`Error `, error);
|
||||
}
|
||||
}
|
||||
|
||||
const syncServers = async () => {
|
||||
try {
|
||||
|
@ -195,6 +318,7 @@ const syncServers = async () => {
|
|||
serverList: settings.servers
|
||||
});
|
||||
console.log(response.data);
|
||||
|
||||
} catch (error) {
|
||||
console.error(`Error `, error);
|
||||
}
|
||||
|
|
28
server/api/deleteServer.ts
Normal file
28
server/api/deleteServer.ts
Normal file
|
@ -0,0 +1,28 @@
|
|||
import {environment} from "~/core/globals";
|
||||
import {removeServerByName, saveJsonFile} from "~/util/jsonLoader";
|
||||
import * as fs from 'fs/promises';
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
const body = await readBody(event);
|
||||
const server_name: string = body.name
|
||||
const server_properties: string = body.properties
|
||||
|
||||
const server = environment.settings.servers.find(server => server.name == server_name);
|
||||
|
||||
if(!server) {
|
||||
return { message: "Server with name " + server_name + " does not exist" };
|
||||
}
|
||||
|
||||
try {
|
||||
console.log("Recived server list");
|
||||
removeServerByName(server.name);
|
||||
const logsPath = environment.paths.servers + "/" + server.name
|
||||
await fs.rmdir(logsPath)
|
||||
saveJsonFile()
|
||||
|
||||
return { status: 'success' };
|
||||
} catch (error) {
|
||||
return { status: 'error', error: error };
|
||||
}
|
||||
});
|
||||
|
|
@ -23,11 +23,16 @@ export default defineEventHandler(async (event) => {
|
|||
try {
|
||||
|
||||
const data = await fs.readFile(logsPath, 'utf-8');
|
||||
const strippedLogs = data.slice(0, -2);
|
||||
return {
|
||||
message: `Logs for ${server_name}`,
|
||||
logs: data
|
||||
logs: strippedLogs
|
||||
};
|
||||
} catch (error: any) {
|
||||
return { message: "Failed to get logs for " + server_name, error: error.message };
|
||||
return {
|
||||
message: "Failed to get logs for " + server_name,
|
||||
logs: "",
|
||||
error: error.message
|
||||
};
|
||||
}
|
||||
});
|
||||
|
|
32
server/api/getProperties.ts
Normal file
32
server/api/getProperties.ts
Normal file
|
@ -0,0 +1,32 @@
|
|||
import {environment} from "~/core/globals";
|
||||
import { defineEventHandler, getCookie, createError } from 'h3';
|
||||
import {saveJsonFile} from "~/util/jsonLoader";
|
||||
import {MinecraftServer} from "~/types/MinecraftServer";
|
||||
import {execa} from "execa";
|
||||
import * as fs from 'fs/promises';
|
||||
|
||||
|
||||
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 logsPath = environment.paths.servers + "/" + server.name + "/server.properties";
|
||||
|
||||
try {
|
||||
const data = await fs.readFile(logsPath, 'utf-8');
|
||||
return {
|
||||
message: `properties for ${server_name}`,
|
||||
properties: data
|
||||
};
|
||||
} catch (error: any) {
|
||||
return { message: "Failed to get logs for " + server_name, error: error.message };
|
||||
}
|
||||
});
|
32
server/api/setProperties.ts
Normal file
32
server/api/setProperties.ts
Normal file
|
@ -0,0 +1,32 @@
|
|||
import {environment} from "~/core/globals";
|
||||
import { defineEventHandler, getCookie, createError } from 'h3';
|
||||
import {saveJsonFile} from "~/util/jsonLoader";
|
||||
import {MinecraftServer} from "~/types/MinecraftServer";
|
||||
import {execa} from "execa";
|
||||
import * as fs from 'fs/promises';
|
||||
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
const body = await readBody(event);
|
||||
const server_name: string = body.name
|
||||
const server_properties: string = body.properties
|
||||
|
||||
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 logsPath = environment.paths.servers + "/" + server.name + "/server.properties";
|
||||
|
||||
try {
|
||||
await fs.writeFile(logsPath, server_properties, 'utf8');
|
||||
return {
|
||||
message: `properties for ${server_name} set`,
|
||||
};
|
||||
} catch (error: any) {
|
||||
return { message: "Failed to get logs for " + server_name, error: error.message };
|
||||
}
|
||||
});
|
|
@ -23,13 +23,19 @@ export default defineEventHandler(async (event) => {
|
|||
const jarPath = environment.paths.servers + "/" + server.name + "/server.jar";
|
||||
|
||||
try {
|
||||
server.process = execa('java', ['-jar', jarPath, 'nogui'], {
|
||||
|
||||
const xmsArg = `-Xms${server.maxMemory}G`
|
||||
const xmxArg = `-Xmx${server.maxMemory}G`
|
||||
|
||||
console.log(`Starting server ${server.name} with ${xmsArg} and ${xmxArg}`);
|
||||
|
||||
server.process = execa('java', [xmsArg, xmxArg, '-jar', jarPath, 'nogui'], {
|
||||
cwd: workingDir,
|
||||
});
|
||||
|
||||
server.process.stdout.on('data', (data: string) => {
|
||||
const logData = data.toString();
|
||||
console.log(logData);
|
||||
//console.log(logData);
|
||||
});
|
||||
|
||||
server.process.stderr.on('data', (data: string) => {
|
||||
|
|
|
@ -16,9 +16,6 @@ export default defineEventHandler(async (event) => {
|
|||
return { message: "Minecraft server is not running." };
|
||||
}
|
||||
|
||||
console.log(server.process)
|
||||
|
||||
console.log("currently contains: " + server.process)
|
||||
|
||||
try {
|
||||
// Send "stop" command to the server process stdin
|
||||
|
|
|
@ -1,14 +1,23 @@
|
|||
import type {ResultPromise} from "execa";
|
||||
import {environment} from "~/core/globals";
|
||||
|
||||
export interface MinecraftServer {
|
||||
name: string;
|
||||
port: number;
|
||||
version: string;
|
||||
jar_url: string;
|
||||
|
||||
minMemory: number;
|
||||
maxMemory: number;
|
||||
|
||||
process: any;
|
||||
|
||||
}
|
||||
|
||||
|
||||
export function getServerDirectory (server: MinecraftServer): string {
|
||||
return environment.paths.servers + "/" + server.name
|
||||
}
|
||||
|
||||
export function getJarPath (server: MinecraftServer): string {
|
||||
return environment.paths.servers + "/" + server.name + "/server.jar"
|
||||
}
|
||||
|
||||
export function getPropertiesPath (server: MinecraftServer): string {
|
||||
return environment.paths.servers + "/" + server.name + "/server.properties"
|
||||
}
|
||||
|
|
|
@ -69,13 +69,23 @@ export function checkAllServerDirectories(){
|
|||
})
|
||||
|
||||
environment.settings.servers.forEach(server => {
|
||||
const destinationPath = environment.paths.servers + "/" + server.name + "/server.jar"
|
||||
const destinationPathJar = environment.paths.servers + "/" + server.name + "/server.jar"
|
||||
const destinationPathEula = environment.paths.servers + "/" + server.name + "/eula.txt"
|
||||
try {
|
||||
fs.accessSync(destinationPath);
|
||||
fs.accessSync(destinationPathJar);
|
||||
console.log('Settings already exists!');
|
||||
} catch (error) {
|
||||
downloadFile(server.jar_url, destinationPath);
|
||||
downloadFile(server.jar_url, destinationPathJar);
|
||||
}
|
||||
|
||||
try {
|
||||
fs.accessSync(destinationPathEula);
|
||||
console.log('eula exists');
|
||||
} catch (error) {
|
||||
console.log("setting eula to true")
|
||||
fs.writeFileSync(destinationPathEula, 'eula=true');
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue