Switch to hsconsole package & add proper shutdown procedure
This commit is contained in:
parent
c80dcd2d4f
commit
ad83454afa
7 changed files with 53 additions and 97 deletions
90
console.ts
90
console.ts
|
@ -1,90 +0,0 @@
|
||||||
import * as dyetty from "dyetty";
|
|
||||||
import { createWriteStream, mkdirSync, existsSync } from "fs";
|
|
||||||
|
|
||||||
console.clear();
|
|
||||||
|
|
||||||
enum LogType {
|
|
||||||
INFO,
|
|
||||||
WARN,
|
|
||||||
ERROR
|
|
||||||
}
|
|
||||||
|
|
||||||
enum LogTag {
|
|
||||||
INFO,
|
|
||||||
CHAT,
|
|
||||||
WARN,
|
|
||||||
ERROR
|
|
||||||
}
|
|
||||||
|
|
||||||
const LogTags = [
|
|
||||||
dyetty.bgGreen(dyetty.black(" INFO ")),
|
|
||||||
dyetty.bgCyan(dyetty.black(" CHAT ")),
|
|
||||||
dyetty.bgYellow(dyetty.black(" WARN ")),
|
|
||||||
dyetty.bgRed(" ERRR ")
|
|
||||||
] as const;
|
|
||||||
|
|
||||||
const TagsForFile = [
|
|
||||||
"[INFO]",
|
|
||||||
"[CHAT]",
|
|
||||||
"[WARN]",
|
|
||||||
"[ERRR]"
|
|
||||||
] as const;
|
|
||||||
|
|
||||||
function correctValue(i:number) : string {
|
|
||||||
if (i <= 9) return `0${i}`;
|
|
||||||
else return i.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
function getTime() : string {
|
|
||||||
const time = new Date();
|
|
||||||
return `[${correctValue(time.getHours())}:${correctValue(time.getMinutes())}:${correctValue(time.getSeconds())}]`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function log(tag:LogTag, log:string, logType:LogType = LogType.INFO) : void {
|
|
||||||
const stringTime = getTime(),
|
|
||||||
fileTag = TagsForFile[tag],
|
|
||||||
consoleTag = LogTags[tag];
|
|
||||||
|
|
||||||
Console.QUEUED_FOR_LOG += `${stringTime} ${fileTag} ${log}\n`;
|
|
||||||
switch (logType) {
|
|
||||||
case LogType.INFO:
|
|
||||||
return console.log(`${dyetty.green(stringTime)} ${consoleTag} ${log}`);
|
|
||||||
case LogType.WARN:
|
|
||||||
return console.warn(`${dyetty.green(stringTime)} ${consoleTag} ${log}`);
|
|
||||||
case LogType.ERROR:
|
|
||||||
return console.error(`${dyetty.green(stringTime)} ${consoleTag} ${log}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Keep old logs, rename on startup using file header?
|
|
||||||
if (!existsSync("./logs")) {
|
|
||||||
mkdirSync("./logs/");
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Console {
|
|
||||||
public static QUEUED_FOR_LOG:string = "";
|
|
||||||
private static logFileWriteStream = createWriteStream("./logs/latest.log");
|
|
||||||
private static flushTimer:NodeJS.Timer = setInterval(() => {
|
|
||||||
if (Console.QUEUED_FOR_LOG.length !== 0) {
|
|
||||||
const strRef = Console.QUEUED_FOR_LOG;
|
|
||||||
Console.QUEUED_FOR_LOG = "";
|
|
||||||
Console.logFileWriteStream.write(strRef);
|
|
||||||
}
|
|
||||||
}, 5000);
|
|
||||||
|
|
||||||
public static printInfo(s:string) : void {
|
|
||||||
log(LogTag.INFO, s);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static printChat(s:string) : void {
|
|
||||||
log(LogTag.CHAT, s);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static printWarn(s:string) : void {
|
|
||||||
log(LogTag.WARN, s, LogType.WARN);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static printError(s:string) : void {
|
|
||||||
log(LogTag.ERROR, s, LogType.ERROR);
|
|
||||||
}
|
|
||||||
}
|
|
3
index.ts
3
index.ts
|
@ -1,4 +1,5 @@
|
||||||
import { Config } from "./config";
|
import { Config } from "./config";
|
||||||
|
import { Console } from "hsconsole";
|
||||||
import { readFileSync } from "fs";
|
import { readFileSync } from "fs";
|
||||||
import { MinecraftServer } from "./server/MinecraftServer";
|
import { MinecraftServer } from "./server/MinecraftServer";
|
||||||
import { SaveCompressionType } from "./server/enums/SaveCompressionType";
|
import { SaveCompressionType } from "./server/enums/SaveCompressionType";
|
||||||
|
@ -6,4 +7,6 @@ const tempConfig = JSON.parse(readFileSync("./config.json").toString());
|
||||||
tempConfig.saveCompression = SaveCompressionType[tempConfig.saveCompression];
|
tempConfig.saveCompression = SaveCompressionType[tempConfig.saveCompression];
|
||||||
const config:Config = tempConfig as Config;
|
const config:Config = tempConfig as Config;
|
||||||
|
|
||||||
|
Console.customHeader(`MC Beta Server started at ${new Date()}`);
|
||||||
|
|
||||||
new MinecraftServer(config);
|
new MinecraftServer(config);
|
10
package-lock.json
generated
10
package-lock.json
generated
|
@ -10,7 +10,7 @@
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bufferstuff": "^1.3.0",
|
"bufferstuff": "^1.3.0",
|
||||||
"dyetty": "^1.0.1"
|
"hsconsole": "^1.0.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^20.4.5",
|
"@types/node": "^20.4.5",
|
||||||
|
@ -1173,6 +1173,14 @@
|
||||||
"integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
|
"integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/hsconsole": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/hsconsole/-/hsconsole-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-st+jaSpNw3uoIhE5vl2lVN8Op8yQF2FyLRdBG68s8vqjduJdKUGtoEXd8Zxe6du1zzpFHHRcU3zJbAq8BOmYQA==",
|
||||||
|
"dependencies": {
|
||||||
|
"dyetty": "^1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ignore-by-default": {
|
"node_modules/ignore-by-default": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
"homepage": "https://github.com/tgpholly/mc-beta-server#readme",
|
"homepage": "https://github.com/tgpholly/mc-beta-server#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bufferstuff": "^1.3.0",
|
"bufferstuff": "^1.3.0",
|
||||||
"dyetty": "^1.0.1"
|
"hsconsole": "^1.0.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^20.4.5",
|
"@types/node": "^20.4.5",
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Console } from "../console";
|
import { Console } from "hsconsole";
|
||||||
import { IReader } from "bufferstuff";
|
import { IReader } from "bufferstuff";
|
||||||
import { MinecraftServer } from "./MinecraftServer";
|
import { MinecraftServer } from "./MinecraftServer";
|
||||||
import { Packet } from "./enums/Packet";
|
import { Packet } from "./enums/Packet";
|
||||||
|
@ -80,7 +80,7 @@ export class MPClient {
|
||||||
Console.printInfo(packet.message = `Teleported ${this.entity.username} to ${message[1]} ${message[2]} ${message[3]}`);
|
Console.printInfo(packet.message = `Teleported ${this.entity.username} to ${message[1]} ${message[2]} ${message[3]}`);
|
||||||
} else if (message[0] === "/csay") {
|
} else if (message[0] === "/csay") {
|
||||||
const consoleMessage = `[CONSOLE] ${message.slice(1, message.length).join(" ")}`;
|
const consoleMessage = `[CONSOLE] ${message.slice(1, message.length).join(" ")}`;
|
||||||
Console.printChat(consoleMessage);
|
Console.printInfo(`[CHAT] ${consoleMessage}`);
|
||||||
this.mcServer.sendToAllClients(new PacketChat(consoleMessage).writeData());
|
this.mcServer.sendToAllClients(new PacketChat(consoleMessage).writeData());
|
||||||
} else if (message[0] === "/top") {
|
} else if (message[0] === "/top") {
|
||||||
// TODO: Figure out why this is broken
|
// TODO: Figure out why this is broken
|
||||||
|
@ -98,7 +98,7 @@ export class MPClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
packet.message = `<${this.entity.username}> ${packet.message}`;
|
packet.message = `<${this.entity.username}> ${packet.message}`;
|
||||||
Console.printChat(packet.message);
|
Console.printInfo(`[CHAT] ${packet.message}`);
|
||||||
this.mcServer.sendToAllClients(packet.writeData());
|
this.mcServer.sendToAllClients(packet.writeData());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Config } from "../config";
|
import { Config } from "../config";
|
||||||
import { Console } from "../console";
|
import { Console } from "hsconsole";
|
||||||
import { createReader, IReader, Endian } from "bufferstuff";
|
import { createReader, IReader, Endian } from "bufferstuff";
|
||||||
import { FunkyArray } from "../funkyArray";
|
import { FunkyArray } from "../funkyArray";
|
||||||
import { Server, Socket } from "net";
|
import { Server, Socket } from "net";
|
||||||
|
@ -17,6 +17,7 @@ import { Player } from "./entities/Player";
|
||||||
import { SaveCompressionType } from "./enums/SaveCompressionType";
|
import { SaveCompressionType } from "./enums/SaveCompressionType";
|
||||||
import { WorldSaveManager } from "./WorldSaveManager";
|
import { WorldSaveManager } from "./WorldSaveManager";
|
||||||
import { World } from "./World";
|
import { World } from "./World";
|
||||||
|
import { Chunk } from "./Chunk";
|
||||||
|
|
||||||
export class MinecraftServer {
|
export class MinecraftServer {
|
||||||
private static readonly PROTOCOL_VERSION = 14;
|
private static readonly PROTOCOL_VERSION = 14;
|
||||||
|
@ -51,6 +52,37 @@ export class MinecraftServer {
|
||||||
public constructor(config:Config) {
|
public constructor(config:Config) {
|
||||||
this.config = config;
|
this.config = config;
|
||||||
|
|
||||||
|
process.on("SIGINT", async (signal) => {
|
||||||
|
Console.printInfo("Shutting down...");
|
||||||
|
// Stop the server timer
|
||||||
|
clearInterval(this.serverClock);
|
||||||
|
// Disconnect all players
|
||||||
|
const kickPacket = new PacketDisconnectKick("Server shutting down.").writeData();
|
||||||
|
this.sendToAllClients(kickPacket);
|
||||||
|
// Shut down the tcp server
|
||||||
|
this.server.close();
|
||||||
|
// Save chunks
|
||||||
|
Console.printInfo("Saving worlds...");
|
||||||
|
let savedWorldCount = 0;
|
||||||
|
let savedChunkCount = 0;
|
||||||
|
await this.worlds.forEach(async (world) => {
|
||||||
|
if (world.chunks.length !== 0) {
|
||||||
|
await world.chunks.forEach(async (chunk) => {
|
||||||
|
await world.unloadChunk(Chunk.CreateCoordPair(chunk.x, chunk.z));
|
||||||
|
savedChunkCount++;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
savedWorldCount++;
|
||||||
|
});
|
||||||
|
Console.printInfo(`Saved ${savedChunkCount} chunks from ${savedWorldCount} world(s).`);
|
||||||
|
|
||||||
|
// Flush final console log to disk and close all writers
|
||||||
|
Console.cleanup();
|
||||||
|
|
||||||
|
// hsconsole is gone now so we have to use built in.
|
||||||
|
console.log("Goodbye");
|
||||||
|
});
|
||||||
|
|
||||||
if (this.config.saveCompression === SaveCompressionType.NONE) {
|
if (this.config.saveCompression === SaveCompressionType.NONE) {
|
||||||
Console.printWarn("=============- WARNING -=============");
|
Console.printWarn("=============- WARNING -=============");
|
||||||
Console.printWarn(" Chunk compression is disabled. This");
|
Console.printWarn(" Chunk compression is disabled. This");
|
||||||
|
|
|
@ -7,6 +7,9 @@
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"rootDir": "./",
|
"rootDir": "./",
|
||||||
"outDir": "./build",
|
"outDir": "./build",
|
||||||
"strict": true
|
"strict": true,
|
||||||
|
"lib": [
|
||||||
|
"ES2021.String"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue