Compare commits
4 Commits
26a7ab742e
...
8e80151331
Author | SHA1 | Date | |
---|---|---|---|
8e80151331 | |||
13e730df7b | |||
c4286373e3 | |||
d71d78319a |
25
.gitignore
vendored
25
.gitignore
vendored
@ -1,23 +1,2 @@
|
|||||||
# ---> Go
|
# NPM dependencies
|
||||||
# If you prefer the allow list template instead of the deny list, see community template:
|
node_modules/
|
||||||
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
|
|
||||||
#
|
|
||||||
# Binaries for programs and plugins
|
|
||||||
*.exe
|
|
||||||
*.exe~
|
|
||||||
*.dll
|
|
||||||
*.so
|
|
||||||
*.dylib
|
|
||||||
|
|
||||||
# Test binary, built with `go test -c`
|
|
||||||
*.test
|
|
||||||
|
|
||||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
|
||||||
*.out
|
|
||||||
|
|
||||||
# Dependency directories (remove the comment below to include it)
|
|
||||||
# vendor/
|
|
||||||
|
|
||||||
# Go workspace file
|
|
||||||
go.work
|
|
||||||
|
|
||||||
|
2
LICENSE
2
LICENSE
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) <year> <owner>
|
Copyright (c) 2022 Bit Goblin
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
40
app/MinecraftServer.js
Normal file
40
app/MinecraftServer.js
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
const fs = require('fs');
|
||||||
|
|
||||||
|
class Server {
|
||||||
|
constructor(dir) {
|
||||||
|
this.rootDir = dir;
|
||||||
|
this.name = dir.split('/').at(-1);
|
||||||
|
this.pidFilePath = this.rootDir + '/pid.txt';
|
||||||
|
|
||||||
|
// read version file
|
||||||
|
var versionFilePath = this.rootDir + '/current_version.txt';
|
||||||
|
if (fs.existsSync(versionFilePath)) {
|
||||||
|
this.version = fs.readFileSync(versionFilePath, {encoding:'utf8', flag:'r'});
|
||||||
|
}
|
||||||
|
|
||||||
|
// set server state
|
||||||
|
if (fs.existsSync(this.pidFilePath)) {
|
||||||
|
this.state = true;
|
||||||
|
} else {
|
||||||
|
this.state = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
start() {
|
||||||
|
console.log('Starting server...');
|
||||||
|
}
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
console.log('Stopping server...');
|
||||||
|
}
|
||||||
|
|
||||||
|
getPid() {
|
||||||
|
if (fs.existsSync(this.pidFilePath)) {
|
||||||
|
return fs.readFileSync(this.pidFilePath, {encoding:'utf8', flag:'r'})
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.Server = Server;
|
3
config/default.json
Normal file
3
config/default.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"server_directory": "/opt/minecraft"
|
||||||
|
}
|
28
index.js
Normal file
28
index.js
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
const express = require('express');
|
||||||
|
const app = express();
|
||||||
|
const port = 3000;
|
||||||
|
|
||||||
|
// set template engine to Pug
|
||||||
|
app.set('view engine', 'pug');
|
||||||
|
|
||||||
|
// Using express.urlencoded middleware
|
||||||
|
app.use(express.urlencoded({
|
||||||
|
extended: true
|
||||||
|
}));
|
||||||
|
|
||||||
|
// import route handlers
|
||||||
|
var homeRoutes = require('./routes/home');
|
||||||
|
var serverRoutes = require('./routes/server');
|
||||||
|
|
||||||
|
// define routes
|
||||||
|
app.get('/', homeRoutes.getIndex);
|
||||||
|
app.get('/server/create', serverRoutes.getCreate);
|
||||||
|
app.post('/server/create', serverRoutes.postCreate);
|
||||||
|
|
||||||
|
// set Express to serve static files (ideally this is only used in development)
|
||||||
|
app.use(express.static('./static/'));
|
||||||
|
|
||||||
|
// start Express.js app
|
||||||
|
app.listen(port, () => {
|
||||||
|
console.log(`Example app listening on port ${port}`);
|
||||||
|
});
|
1670
package-lock.json
generated
Normal file
1670
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
25
package.json
Normal file
25
package.json
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"name": "mcst",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description": "Minecraft Java edition server management tool",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"start": "node index.js",
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "gitea@git.metaunix.net:BitGoblin/mcst.git"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"minecraft",
|
||||||
|
"minecraft java edition",
|
||||||
|
"java"
|
||||||
|
],
|
||||||
|
"author": "Gregory Ballantine <gballantine@bitgoblin.tech>",
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
|
"dependencies": {
|
||||||
|
"express": "^4.18.1",
|
||||||
|
"pug": "^3.0.2"
|
||||||
|
}
|
||||||
|
}
|
19
routes/home.js
Normal file
19
routes/home.js
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
const config = require('config');
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const minecraft = require('../app/MinecraftServer');
|
||||||
|
|
||||||
|
exports.getIndex = function(req, res) {
|
||||||
|
// search for minecraft server directories
|
||||||
|
let rootDir = config.get('server_directory');
|
||||||
|
let serverDirs = fs.readdirSync(rootDir);
|
||||||
|
let servers = [];
|
||||||
|
for (let i = 0; i < serverDirs.length; i++) {
|
||||||
|
servers.push(new minecraft.Server(path.join(rootDir, serverDirs[i])));
|
||||||
|
}
|
||||||
|
|
||||||
|
// render view
|
||||||
|
res.render('index', {
|
||||||
|
servers: servers,
|
||||||
|
});
|
||||||
|
};
|
45
routes/server.js
Normal file
45
routes/server.js
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
const config = require('config');
|
||||||
|
const fs = require('fs');
|
||||||
|
const https = require('https');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
exports.getCreate = function(req, res) {
|
||||||
|
// render view
|
||||||
|
res.render('create');
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.postCreate = function(req, res) {
|
||||||
|
mcDir = config.get('server_directory');
|
||||||
|
serverDir = path.join(mcDir, req.body.serverName);
|
||||||
|
|
||||||
|
// make server directory
|
||||||
|
fs.mkdirSync(serverDir);
|
||||||
|
|
||||||
|
// grab the server JAR file
|
||||||
|
serverJarUrl = 'https://piston-data.mojang.com/v1/objects/f69c284232d7c7580bd89a5a4931c3581eae1378/server.jar';
|
||||||
|
serverJarName = "server_" + req.body.serverVersion + ".jar";
|
||||||
|
serverJarPath = path.join(serverDir, serverJarName);
|
||||||
|
https.get(serverJarUrl, (res) => {
|
||||||
|
const filePath = fs.createWriteStream(serverJarPath);
|
||||||
|
res.pipe(filePath);
|
||||||
|
filePath.on('finish', () => {
|
||||||
|
filePath.close();
|
||||||
|
console.log('Download Completed');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// create the start.sh shell script
|
||||||
|
scriptFilePath = path.join(serverDir, 'start.sh');
|
||||||
|
scriptContent = "#!/bin/sh\n\ncd " + serverDir + "\njava -Xmx2048M -Xms2048M -jar server_" + req.body.serverVersion + ".jar nogui";
|
||||||
|
fs.writeFileSync(scriptFilePath, scriptContent);
|
||||||
|
fs.chmodSync(scriptFilePath, 0o755);
|
||||||
|
|
||||||
|
// save the current version to a text file - this will hopefully be temporary solution
|
||||||
|
versionFilePath = path.join(serverDir, 'current_version.txt');
|
||||||
|
versionContent = req.body.serverVersion;
|
||||||
|
fs.writeFileSync(versionFilePath, versionContent);
|
||||||
|
fs.chmodSync(versionFilePath, 0o644);
|
||||||
|
|
||||||
|
// redirect the user back to the home page
|
||||||
|
res.redirect('/');
|
||||||
|
};
|
46
static/css/wyrm.css
Normal file
46
static/css/wyrm.css
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
body{
|
||||||
|
background-color: #e6e6e6;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set the max-width for centered content */
|
||||||
|
.container{
|
||||||
|
max-width: 1100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main-content{
|
||||||
|
margin-top: 25px;
|
||||||
|
padding: 12px 25px;
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* global navigation bar styles */
|
||||||
|
.navbar{
|
||||||
|
padding: 10px 18px;
|
||||||
|
background-color: #212121;
|
||||||
|
color: white;
|
||||||
|
font-size: 2.5rem;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar ul{
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar li{
|
||||||
|
display: inline-block;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
.navbar li:not(:first-child){
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar li>a{
|
||||||
|
color: #eee;
|
||||||
|
text-decoration: none;
|
||||||
|
transition: color 220ms ease-in-out;
|
||||||
|
}
|
||||||
|
.navbar li>a:hover{
|
||||||
|
color: white;
|
||||||
|
}
|
3
static/js/drake.js
Normal file
3
static/js/drake.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
$(document).ready(function () {
|
||||||
|
// This will be used when needed
|
||||||
|
});
|
24
views/create.pug
Normal file
24
views/create.pug
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
extends layout.pug
|
||||||
|
|
||||||
|
block content
|
||||||
|
header.row
|
||||||
|
div.columns.twelve
|
||||||
|
h1 Create new server
|
||||||
|
|
||||||
|
section.row
|
||||||
|
div.columns.twelve
|
||||||
|
form(action='/server/create', method='POST')
|
||||||
|
div.row
|
||||||
|
div.columns.six
|
||||||
|
label(for='serverName') Server name:
|
||||||
|
input#serverName.u-full-width(name='serverName', type='text', placeholder='MyServer')
|
||||||
|
div.columns.six
|
||||||
|
label(for='serverVersion') Minecraft version:
|
||||||
|
input#serverVersion.u-full-width(name='serverVersion', type='text', placeholder='1.19.2')
|
||||||
|
|
||||||
|
input(type='submit', value='Submit')
|
||||||
|
|
||||||
|
div.row
|
||||||
|
div.columns.twelve
|
||||||
|
p
|
||||||
|
a(href='/') Back
|
30
views/index.pug
Normal file
30
views/index.pug
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
extends layout.pug
|
||||||
|
|
||||||
|
block content
|
||||||
|
header.row
|
||||||
|
div.columns.twelve
|
||||||
|
h1 Welcome to MCST!
|
||||||
|
p Using MCST you can easily manage your Minecraft: Java Edition servers.
|
||||||
|
|
||||||
|
section.row
|
||||||
|
div.columns.twelve
|
||||||
|
h3 List of servers:
|
||||||
|
if servers.length < 1
|
||||||
|
p There are currently no servers registered.
|
||||||
|
else
|
||||||
|
table.u-full-width
|
||||||
|
thead
|
||||||
|
tr
|
||||||
|
th Server name
|
||||||
|
th Minecraft version
|
||||||
|
th State
|
||||||
|
th Actions
|
||||||
|
tbody
|
||||||
|
each m in servers
|
||||||
|
tr.serverItem
|
||||||
|
td.serverName= m.name
|
||||||
|
td.serverVersion= m.version
|
||||||
|
td.serverState= m.state
|
||||||
|
td
|
||||||
|
a(href='/server/' + m.name + '/start') Start
|
||||||
|
a(href='/server/' + m.name + '/stop') Stop
|
21
views/layout.pug
Normal file
21
views/layout.pug
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
doctype html
|
||||||
|
html(lang="en")
|
||||||
|
head
|
||||||
|
title= pageTitle
|
||||||
|
link(rel='stylesheet', href='https://cdnjs.cloudflare.com/ajax/libs/skeleton/2.0.4/skeleton.min.css')
|
||||||
|
link(rel='stylesheet', href='/css/wyrm.css')
|
||||||
|
script(src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.1/jquery.min.js')
|
||||||
|
script(src='/js/drake.js')
|
||||||
|
body
|
||||||
|
// global navigation
|
||||||
|
nav.navbar
|
||||||
|
div.navbar-left
|
||||||
|
ul
|
||||||
|
li.menu-text MCST
|
||||||
|
li: a(href='/') Home
|
||||||
|
li: a(href='/server/create') Create
|
||||||
|
li: a(href='/status') Status
|
||||||
|
|
||||||
|
// main content
|
||||||
|
div#main-content.container
|
||||||
|
block content
|
Loading…
Reference in New Issue
Block a user