Added rcon and query features to get server status and player online counts
This commit is contained in:
		
							parent
							
								
									f386855ed1
								
							
						
					
					
						commit
						11c757b4f0
					
				
							
								
								
									
										92
									
								
								includes/class_server.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								includes/class_server.js
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,92 @@
 | 
			
		|||
const Ping = require('net-ping');
 | 
			
		||||
const Discord = require('discord.js');
 | 
			
		||||
 | 
			
		||||
class Server {
 | 
			
		||||
 | 
			
		||||
    slug = "";
 | 
			
		||||
    name = "";
 | 
			
		||||
    platformURL = "";
 | 
			
		||||
    mcVersion = "";
 | 
			
		||||
    iconURL = "";
 | 
			
		||||
    description = "";
 | 
			
		||||
    addressPrimary = "";
 | 
			
		||||
    addressSecondary = "";
 | 
			
		||||
    queryPort = 0;
 | 
			
		||||
    rconAddress = "";
 | 
			
		||||
    rconPort = 0;
 | 
			
		||||
    rconPassword = "";
 | 
			
		||||
    rconTPSCommand = "";
 | 
			
		||||
    rconOnlineCommand = "";
 | 
			
		||||
    active = false;
 | 
			
		||||
    
 | 
			
		||||
    constructor(serverObj) {
 | 
			
		||||
        if ( serverObj.slug ) this.slug = serverObj.slug;
 | 
			
		||||
        if ( serverObj.name ) this.name = serverObj.name;
 | 
			
		||||
        if ( serverObj.platformURL ) this.platformURL = serverObj.platformURL;
 | 
			
		||||
        if ( serverObj.mcVersion ) this.mcVersion = serverObj.mcVersion;
 | 
			
		||||
        if ( serverObj.iconURL ) this.iconURL = serverObj.iconURL;
 | 
			
		||||
        if ( serverObj.description ) this.description = serverObj.description;
 | 
			
		||||
        if ( serverObj.addressPrimary ) this.addressPrimary = serverObj.addressPrimary;
 | 
			
		||||
        if ( serverObj.addressSecondary ) this.addressSecondary = serverObj.addressSecondary;
 | 
			
		||||
        if ( serverObj.queryPort ) this.queryPort = serverObj.queryPort;
 | 
			
		||||
        if ( serverObj.rconAddress ) this.rconAddress = serverObj.rconAddress;
 | 
			
		||||
        if ( serverObj.rconPort ) this.rconPort = serverObj.rconPort;
 | 
			
		||||
        if ( serverObj.rconPassword ) this.rconPassword = serverObj.rconPassword;
 | 
			
		||||
        if ( serverObj.rconTPSCommand ) this.rconTPSCommand = serverObj.rconTPSCommand;
 | 
			
		||||
        if ( serverObj.rconOnlineCommand ) this.rconOnlineCommand = serverObj.rconOnlineCommand;
 | 
			
		||||
        if ( serverObj.active ) this.active = serverObj.active;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async hostIsAlive() {
 | 
			
		||||
        try {
 | 
			
		||||
            if ( !this.active || (this.rconAddress == "") ) return false;
 | 
			
		||||
            let session = Ping.createSession({retries: 1, timeout: 250});
 | 
			
		||||
            let result = await session.pingHost(this.rconAddress, function(error, target) {
 | 
			
		||||
                if ( error ) {
 | 
			
		||||
                    return false;
 | 
			
		||||
                } else {
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
            return result;
 | 
			
		||||
        } catch (e) {
 | 
			
		||||
            console.log(e);
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static sendOnline(status, channel) {
 | 
			
		||||
        let playerCount = 0;
 | 
			
		||||
        let embed = new Discord.MessageEmbed()
 | 
			
		||||
            .setThumbnail("https://www.circlecraft.info/images/circlecraft_discord.png")
 | 
			
		||||
            .setColor(0x44ff44);
 | 
			
		||||
        status.forEach(function (s) {
 | 
			
		||||
            if ( !s.tested ) return;
 | 
			
		||||
            if ( s.players.length > 0 ) embed.addField("**" + s.name + "**:", s.players.join(', '), false);
 | 
			
		||||
        });
 | 
			
		||||
        embed.setTitle("Players Currently Online: " + playerCount);
 | 
			
		||||
        channel.send(embed);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    sendDetails(channel, hostStatus, serverStatus, serverTPS, queryStatus = {}) {
 | 
			
		||||
        let embed = new Discord.MessageEmbed()
 | 
			
		||||
            .setTitle(this.name + " *(" + this.slug + ")*")
 | 
			
		||||
            .setDescription(this.description)
 | 
			
		||||
            .setURL(this.platformURL)
 | 
			
		||||
            .setThumbnail(this.iconURL)
 | 
			
		||||
            .setColor(0xffaaaa)
 | 
			
		||||
            .addField("**MC Version:**", this.mcVersion, true)
 | 
			
		||||
            .addField("**Server Address:**", this.addressPrimary, true)
 | 
			
		||||
            .addField("**Server Alternate:**", this.addressSecondary, true)
 | 
			
		||||
            .addField("**Host Status:**", hostStatus, true)
 | 
			
		||||
            .addField("**Server Status:**", serverStatus, true)
 | 
			
		||||
            .addField("**Server TPS:**", serverTPS, true);
 | 
			
		||||
        if ( queryStatus.players ) {
 | 
			
		||||
            let players = (queryStatus.players.length > 0) ? queryStatus.players.join(', ') : "None";
 | 
			
		||||
            embed.addField("**Online Players (" + queryStatus.online_players + "):**", players, false);
 | 
			
		||||
        }
 | 
			
		||||
        channel.send(embed);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = Server;
 | 
			
		||||
							
								
								
									
										146
									
								
								index.js
									
									
									
									
									
								
							
							
						
						
									
										146
									
								
								index.js
									
									
									
									
									
								
							| 
						 | 
				
			
			@ -1,6 +1,10 @@
 | 
			
		|||
const Config = require('./config/config.js');
 | 
			
		||||
const Servers = require('./config/servers.js');
 | 
			
		||||
const Config = require('./config/config');
 | 
			
		||||
const Servers = require('./config/servers');
 | 
			
		||||
const Discord = require('discord.js');
 | 
			
		||||
const Rcon = require('mbr-rcon');
 | 
			
		||||
const Query = require("minecraft-query");
 | 
			
		||||
const Server = require('./includes/class_server');
 | 
			
		||||
 | 
			
		||||
const client = new Discord.Client();
 | 
			
		||||
 | 
			
		||||
client.on('ready', () => {
 | 
			
		||||
| 
						 | 
				
			
			@ -9,24 +13,72 @@ client.on('ready', () => {
 | 
			
		|||
 | 
			
		||||
process.on('SIGINT', function() {
 | 
			
		||||
    console.log("Closing down...");
 | 
			
		||||
    process.exit(1);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
let last = "";
 | 
			
		||||
function sendOnline(status, channel) {
 | 
			
		||||
    let playerCount = 0;
 | 
			
		||||
    let embed = new Discord.MessageEmbed()
 | 
			
		||||
        .setThumbnail("https://www.circlecraft.info/images/circlecraft_discord.png")
 | 
			
		||||
        .setColor(0x44ff44);
 | 
			
		||||
    for ( const s in status ) {
 | 
			
		||||
        if ( !status[s].tested ) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        if ( status[s].players.length > 0 ) {
 | 
			
		||||
            playerCount += status[s].players.length;
 | 
			
		||||
            embed.addField("**" + status[s].name + "**:", status[s].players.join(', '), false);
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
    if ( playerCount == 0 ) return;
 | 
			
		||||
    embed.setTitle("**Players Currently Online:** " + playerCount);
 | 
			
		||||
    channel.send(embed);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
client.on('message', msg => {
 | 
			
		||||
client.on('message', async msg => {
 | 
			
		||||
    if ( msg.content.startsWith(">>servers") && Config.CHANNELS_ALLOW.includes(msg.channel.id) ) {
 | 
			
		||||
        let embed = new Discord.MessageEmbed()
 | 
			
		||||
            .setTitle("Here's a list of our current servers...")
 | 
			
		||||
            .setColor(0xFFaaaa);
 | 
			
		||||
        Servers.forEach(function (server) {
 | 
			
		||||
            embed.addField("**" + server.name + "** *(" + server.slug + ")*", server.description);
 | 
			
		||||
            if ( server.active ) embed.addField("**" + server.name + "** *(" + server.slug + ")*", server.description);
 | 
			
		||||
        });
 | 
			
		||||
        embed.setFooter("Get more info on a pack with: >>server slug\nThe slugs are in parenthesis above");
 | 
			
		||||
 | 
			
		||||
        msg.channel.send(embed);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ( msg.content == ">>server" ) {
 | 
			
		||||
    if ( msg.content == ">>online" && Config.CHANNELS_ALLOW.includes(msg.channel.id) ) {
 | 
			
		||||
        let status = [];
 | 
			
		||||
        Servers.forEach(function (server) {
 | 
			
		||||
            if ( server.active ) {
 | 
			
		||||
                status[server.slug] = {tested: false, online: false, players: [], name: ""};
 | 
			
		||||
                status[server.slug].name = server.name;
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
        Servers.forEach(function (server) {
 | 
			
		||||
            const q = new Query({host: server.rconAddress, port: server.queryPort, timeout: 250});
 | 
			
		||||
            try {
 | 
			
		||||
                q.fullStat()
 | 
			
		||||
                    .then(response => {
 | 
			
		||||
                        status[server.slug].tested = true;
 | 
			
		||||
                        status[server.slug].online = true;
 | 
			
		||||
                        status[server.slug].players = response.players;
 | 
			
		||||
                        sendOnline(status, msg.channel);
 | 
			
		||||
                    })
 | 
			
		||||
                    .then(() => { q.close(); })
 | 
			
		||||
                    .catch(e => {
 | 
			
		||||
                        q.close();
 | 
			
		||||
                        status[server.slug].tested = true;
 | 
			
		||||
                        sendOnline(status, msg.channel);
 | 
			
		||||
                    });
 | 
			
		||||
            } catch (e) {
 | 
			
		||||
                console.log(e);
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ( msg.content == ">>server" && Config.CHANNELS_ALLOW.includes(msg.channel.id) ) {
 | 
			
		||||
        msg.channel.send("**Usage:** >>server *slug*");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -34,16 +86,78 @@ client.on('message', msg => {
 | 
			
		|||
        let cmdParts = msg.content.split(" ");
 | 
			
		||||
        let server = Servers.find(element => element.slug == cmdParts[1]);
 | 
			
		||||
        if ( server ) {
 | 
			
		||||
            let embed = new Discord.MessageEmbed()
 | 
			
		||||
                .setTitle(server.name + " *(" + server.slug + ")*")
 | 
			
		||||
                .setDescription(server.description)
 | 
			
		||||
                .setURL(server.platformURL)
 | 
			
		||||
                .setThumbnail(server.iconURL)
 | 
			
		||||
                .setColor(0xffaaaa)
 | 
			
		||||
                .addField("**MC Version:**", server.mcVersion, true)
 | 
			
		||||
                .addField("**Server Address:**", server.addressPrimary, true)
 | 
			
		||||
                .addField("**Server Alternate:**", server.addressSecondary, true);
 | 
			
		||||
            msg.channel.send(embed);
 | 
			
		||||
            let hostStatus = "Offline";
 | 
			
		||||
            try {
 | 
			
		||||
                if (server.hostIsAlive()) hostStatus = "Online";
 | 
			
		||||
            } catch (e) {
 | 
			
		||||
                console.log(e);
 | 
			
		||||
            }
 | 
			
		||||
            //console.log(query);
 | 
			
		||||
            let serverStatus = "Stopped";
 | 
			
		||||
            let serverTPS = "---";
 | 
			
		||||
            if ( server.rconPort != 0 ) {
 | 
			
		||||
                //console.log("Making new rcon connection...");
 | 
			
		||||
                const rcon = new Rcon({
 | 
			
		||||
                    host: server.rconAddress,
 | 
			
		||||
                    port: server.rconPort,
 | 
			
		||||
                    pass: server.rconPassword,
 | 
			
		||||
                    onClose: function () {}
 | 
			
		||||
                });
 | 
			
		||||
                const connection = rcon.connect({
 | 
			
		||||
                    onSuccess: function() {
 | 
			
		||||
                        //console.log("Connected! " + serverStatus);
 | 
			
		||||
                        serverStatus = "Running";
 | 
			
		||||
                    },
 | 
			
		||||
                    onError: function() {
 | 
			
		||||
                        console.log("Could not connect to rcon server: " + server.name + " " + server.rconAddress + " " + server.rconPort);
 | 
			
		||||
                        server.sendDetails(msg.channel, hostStatus, serverStatus, serverTPS);
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
                connection.auth({
 | 
			
		||||
                    onSuccess: function () {
 | 
			
		||||
                        //console.log("Successfully authenticated to: " + server.name);
 | 
			
		||||
                    },
 | 
			
		||||
                    onError: function (error) {
 | 
			
		||||
                        console.log("Could not authenticate to rcon server: " + server.name + " " + server.rconAddress + " " + server.rconPort);
 | 
			
		||||
                        server.sendDetails(msg.channel, hostStatus, serverStatus, serverTPS);
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
                await connection.send(server.rconTPSCommand, {
 | 
			
		||||
                    onSuccess: function (response) {
 | 
			
		||||
                        //console.log(response);
 | 
			
		||||
                        if ( ['1.2.5', '1.4.7'].includes(server.mcVersion) ) {
 | 
			
		||||
                            let tpsParts = response.trim().split("\n");
 | 
			
		||||
                            serverTPS = tpsParts[0].split(" ").pop().slice(2);
 | 
			
		||||
                        } else {
 | 
			
		||||
                            let tpsParts = response.trim().split(" ");
 | 
			
		||||
                            serverTPS = tpsParts.pop();
 | 
			
		||||
                            if ( serverTPS.includes("*") ) serverTPS = serverTPS.split("*").pop();
 | 
			
		||||
                        }
 | 
			
		||||
                        //console.log("Got it all!_" + hostStatus + "_" + serverStatus + "_" + serverTPS + "_");
 | 
			
		||||
                        const q = new Query({host: server.rconAddress, port: server.queryPort, timeout: 250});
 | 
			
		||||
                        try {
 | 
			
		||||
                            q.fullStat()
 | 
			
		||||
                                .then(response => {
 | 
			
		||||
                                    server.sendDetails(msg.channel, hostStatus, serverStatus, serverTPS, response);
 | 
			
		||||
                                })
 | 
			
		||||
                                .then(() => { q.close(); })
 | 
			
		||||
                                .catch(e => {
 | 
			
		||||
                                    q.close();
 | 
			
		||||
                                    server.sendDetails(msg.channel, hostStatus, serverStatus, serverTPS);
 | 
			
		||||
                                });
 | 
			
		||||
                        } catch (e) {
 | 
			
		||||
                            console.log(e);
 | 
			
		||||
                        }
 | 
			
		||||
                    },
 | 
			
		||||
                    onError: function (error) {
 | 
			
		||||
                        console.log("Could not query rcon server: " + server.name + " " + server.rconAddress + " " + server.rconPort);
 | 
			
		||||
                        server.sendDetails(msg.channel, hostStatus, serverStatus, serverTPS);
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
            } else {
 | 
			
		||||
                console.log("No rcon settings for: " + server.name);
 | 
			
		||||
                server.sendDetails(msg.channel, hostStatus, serverStatus, serverTPS);
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            if ( cmdParts[1] ) {
 | 
			
		||||
                msg.channel.send("No server with the slug \"" + cmdParts[1] + "\" exists");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										58
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										58
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| 
						 | 
				
			
			@ -553,6 +553,25 @@
 | 
			
		|||
        "pify": "^3.0.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "mbr-buffer": {
 | 
			
		||||
      "version": "1.3.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/mbr-buffer/-/mbr-buffer-1.3.0.tgz",
 | 
			
		||||
      "integrity": "sha512-4CFPovz0jVLf9MVgez9iMz6u8yG8PxJTncr7Y4rzDCeu8y9NQNad+mCrVjKpvYndkKF9pP2DiTnzBKzdqhMZ9g=="
 | 
			
		||||
    },
 | 
			
		||||
    "mbr-queue": {
 | 
			
		||||
      "version": "1.0.3",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/mbr-queue/-/mbr-queue-1.0.3.tgz",
 | 
			
		||||
      "integrity": "sha512-u0tJHtLXrE8ImxCMZoZjWocn/9A1rV7m+GxaWh+GjMsHp3KjcVmGVKIb1IEiUH/vkwTJ9AuqwQCbd6h0qqyR+g=="
 | 
			
		||||
    },
 | 
			
		||||
    "mbr-rcon": {
 | 
			
		||||
      "version": "1.1.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/mbr-rcon/-/mbr-rcon-1.1.0.tgz",
 | 
			
		||||
      "integrity": "sha512-JPUFGFjQFfXImyOwap4ssvPrqQhO75ZJFGXkAVzK5M1bean2d+SVDlYywENtKThUtRHeFvKJC6e2q6XD97Z4pg==",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "mbr-buffer": "^1.2.2",
 | 
			
		||||
        "mbr-queue": "^1.0.3"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "mime-db": {
 | 
			
		||||
      "version": "1.43.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -566,6 +585,11 @@
 | 
			
		|||
        "mime-db": "1.43.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "minecraft-query": {
 | 
			
		||||
      "version": "1.0.9",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/minecraft-query/-/minecraft-query-1.0.9.tgz",
 | 
			
		||||
      "integrity": "sha512-RCVT45MRV5MjNMSOFPKVWD5cj+V1TAREQ0irHPUBDKrnVl4WaQzcqhEyXwWZ2LRaR2GiUI6TtMBklTytFrJ+tA=="
 | 
			
		||||
    },
 | 
			
		||||
    "minimatch": {
 | 
			
		||||
      "version": "3.0.4",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -592,6 +616,19 @@
 | 
			
		|||
      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "nan": {
 | 
			
		||||
      "version": "2.14.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz",
 | 
			
		||||
      "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg=="
 | 
			
		||||
    },
 | 
			
		||||
    "net-ping": {
 | 
			
		||||
      "version": "1.2.3",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/net-ping/-/net-ping-1.2.3.tgz",
 | 
			
		||||
      "integrity": "sha512-ZKxj/kVPKL2RIsV9nR6I8nMT8Pi3k6ciTBKxD/6gd5lga9qcNmlyqNv+dbXqYGBvHsmG9yIpsfajr8X054x2fQ==",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "raw-socket": "*"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node-fetch": {
 | 
			
		||||
      "version": "2.6.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -704,6 +741,14 @@
 | 
			
		|||
      "integrity": "sha512-xsMgrUwRpuGskEzBFkH8NmTimbZ5PcPup0LA8JJkHIm2IMUbQcpo3yeLNWVrufEYjh8YwtSVh0xz6UeWc5Oh5A==",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "raw-socket": {
 | 
			
		||||
      "version": "1.7.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/raw-socket/-/raw-socket-1.7.0.tgz",
 | 
			
		||||
      "integrity": "sha512-mXqWihgwaFNmV5le0dWk5o+03M3A2zBIkC9BNaE6R0CJN9eYot++j2FIqgNSDq6/Vmu32PPI155SiiWNV2yyFQ==",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "nan": "2.14.*"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "rc": {
 | 
			
		||||
      "version": "1.2.8",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -716,14 +761,6 @@
 | 
			
		|||
        "strip-json-comments": "~2.0.1"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "rcon-client": {
 | 
			
		||||
      "version": "4.2.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/rcon-client/-/rcon-client-4.2.0.tgz",
 | 
			
		||||
      "integrity": "sha512-PXoGQiO6ztssnveLkY/AqMnokuzv+Ml8Zij65fYQ98N873KP2eiV+DbN3rijC7vfMgyy2DSKZ2gjoGD9iCPjVg==",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "typed-emitter": "^0.1.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "readdirp": {
 | 
			
		||||
      "version": "3.3.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.3.0.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -877,11 +914,6 @@
 | 
			
		|||
      "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz",
 | 
			
		||||
      "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw=="
 | 
			
		||||
    },
 | 
			
		||||
    "typed-emitter": {
 | 
			
		||||
      "version": "0.1.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/typed-emitter/-/typed-emitter-0.1.0.tgz",
 | 
			
		||||
      "integrity": "sha512-Tfay0l6gJMP5rkil8CzGbLthukn+9BN/VXWcABVFPjOoelJ+koW8BuPZYk+h/L+lEeIp1fSzVRiWRPIjKVjPdg=="
 | 
			
		||||
    },
 | 
			
		||||
    "undefsafe": {
 | 
			
		||||
      "version": "2.0.3",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.3.tgz",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,7 +22,9 @@
 | 
			
		|||
    "tweetnacl": "^1.0.3",
 | 
			
		||||
    "ws": "^7.2.3",
 | 
			
		||||
    "moment": "^2.24.0",
 | 
			
		||||
    "rcon-client": "^4.2.0"
 | 
			
		||||
    "net-ping": "^1.2.3",
 | 
			
		||||
    "mbr-rcon": "^1.1.0",
 | 
			
		||||
    "minecraft-query": "^1.0.9"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "nodemon": "^2.0.2"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user