Fix: mcping module

This commit is contained in:
Unitwk 2024-08-13 15:03:57 +08:00
parent aef539633d
commit c2f806e70d
2 changed files with 51 additions and 94 deletions

View File

@ -1,22 +1,13 @@
// Using SLT (Server List Ping) provided by Minecraft.
// Since it is part of the protocol it is always enabled contrary to Query
// More information at: https://wiki.vg/Server_List_Ping#Response
// Github: https://github.com/Vaksty/mcping
// https://wiki.vg/Server_List_Ping#Response
import net from "net";
function formatMotd(motd: any) {
let noSpaces = motd.replace(/\u0000/g, "");
Buffer.from(noSpaces);
// let noColor = noSpaces.toString().replace(/[^\x00-\x7F]/g, '');
// console.log(Buffer.from(motd, 'utf8').toString('hex'));
// console.log(noColor);
}
export default class MCServStatus {
export default class PingMinecraftServer {
public port: number;
public host: string;
public status: any;
public client?: net.Socket;
constructor(port: number, host: string) {
this.port = port;
@ -34,16 +25,16 @@ export default class MCServStatus {
getStatus() {
return new Promise((resolve, reject) => {
var start_time = new Date().getTime();
const client = net.connect(this.port, this.host, () => {
this.client = net.connect(this.port, this.host, () => {
this.status.latency = Math.round(new Date().getTime() - start_time);
// 0xFE packet identifier for a server list ping
// 0x01 server list ping's payload (always 1)
let data = Buffer.from([0xfe, 0x01]);
client.write(data);
this?.client?.write(data);
});
// The client can also receive data from the server by reading from its socket.
client.on("data", (response: any) => {
this?.client?.on("data", (response: any) => {
// Check the readme for a simple explanation
var server_info = response.toString().split("\x00\x00");
@ -57,24 +48,64 @@ export default class MCServStatus {
max_players: server_info[5].replace(/\u0000/g, ""),
latency: this.status.latency
};
formatMotd(server_info[3]);
// Request an end to the connection after the data has been received.
client.end();
this?.client?.end();
resolve(this.status);
this.destroy();
});
client.on("end", () => {
// console.log('Requested an end to the TCP connection');
this?.client?.on("end", () => {
resolve(this.status);
this.destroy();
});
client.on("error", (err: any) => {
this?.client?.on("error", (err: any) => {
reject(err);
this.destroy();
});
});
}
private destroy() {
this.client?.removeAllListeners();
}
async asyncStatus() {
let status = await this.getStatus();
return status;
}
}
// async function test() {
// try {
// var status = await new MCServStatus(25565, "localhost").asyncStatus();
// // console.log("status: ", status);
// } catch (error) {
// console.error("错误:", error);
// }
// const memoryUsage = process.memoryUsage();
// console.log(
// "RSS (Resident Set Size):",
// (memoryUsage.rss / 1024 / 1024).toFixed(2),
// "MB",
// "Heap Total:",
// (memoryUsage.heapTotal / 1024 / 1024).toFixed(2),
// "MB",
// "Heap Used:",
// (memoryUsage.heapUsed / 1024 / 1024).toFixed(2),
// "MB",
// "External:",
// (memoryUsage.external / 1024 / 1024).toFixed(2),
// "MB"
// );
// // console.log("Heap Total:", (memoryUsage.heapTotal / 1024 / 1024).toFixed(2), "MB");
// // console.log("External:", (memoryUsage.external / 1024 / 1024).toFixed(2), "MB");
// // console.log("Heap Used:", (memoryUsage.heapUsed / 1024 / 1024).toFixed(2), "MB");
// }
// for (let index = 0; index < 10000; index++) {
// test();
// // @ts-ignore
// // global.gc();
// }

View File

@ -1,74 +0,0 @@
import { ILifeCycleTask } from "../../instance/life_cycle";
import Instance from "../../instance/instance";
export default class RefreshPlayer implements ILifeCycleTask {
public name: string = "RefreshPlayer";
public status: number = 0;
private task: any = null;
private playersChartTask: any = null;
private playersChart: Array<{ value: string }> = [];
async start(instance: Instance) {
this.task = setInterval(async () => {
// {
// host: 'localhost',
// port: 28888,
// status: true,
// version: '1.17.1',
// motd: 'A Minecraft Server',
// current_players: '0',
// max_players: '20',
// latency: 1
// }
try {
// Get information such as the number of players, version, etc.
const result = await instance.execPreset("getPlayer");
if (!result) return;
instance.info.maxPlayers = result.max_players ? result.max_players : -1;
instance.info.currentPlayers = result.current_players ? result.current_players : -1;
instance.info.version = result.version ? result.version : "";
// When the number of users is correctly obtained for the first time, initialize the number of players graph
if (this.playersChart.length === 0) {
this.initPlayersChart(instance);
}
} catch (error: any) {}
}, 3000);
// Start the timer for querying the online population report data
this.playersChartTask = setInterval(() => {
this.getPlayersChartData(instance);
}, 600000);
}
initPlayersChart(instance: Instance) {
while (this.playersChart.length < 60) {
this.playersChart.push({ value: "0" });
}
instance.info.playersChart = this.playersChart;
this.getPlayersChartData(instance);
}
getPlayersChartData(instance: Instance) {
try {
this.playersChart.shift();
this.playersChart.push({
value: String(instance.info.currentPlayers) ?? "0"
});
instance.info.playersChart = this.playersChart;
} catch (error: any) {}
}
async stop(instance: Instance) {
clearInterval(this.task);
clearInterval(this.playersChartTask);
instance.info.maxPlayers = -1;
instance.info.currentPlayers = -1;
instance.info.version = "";
instance.info.playersChart = [];
this.playersChart = [];
this.playersChartTask = null;
this.task = null;
}
}