Implement RCON (#72)
This commit is contained in:
parent
24c7f0e155
commit
038c4a44d5
11
package-lock.json
generated
11
package-lock.json
generated
@ -12,6 +12,7 @@
|
||||
"mongodb": "^4.8.0",
|
||||
"node-kcp-token": "github:memetrollsxd/node-kcp",
|
||||
"protobufjs": "^7.0.0",
|
||||
"rcon-server": "^0.1.1",
|
||||
"typescript": "^4.7.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
@ -1202,6 +1203,11 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/rcon-server": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/rcon-server/-/rcon-server-0.1.1.tgz",
|
||||
"integrity": "sha512-oJ9+s0yxGc7in6GBBBxFXKRY2OyIVxFsoAEHlo5iFXDCuK6O4gY4qJ9XndMBVmA+nABkyOrN6QAFzoE6wZiI7A=="
|
||||
},
|
||||
"node_modules/readdirp": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
||||
@ -2568,6 +2574,11 @@
|
||||
"unpipe": "1.0.0"
|
||||
}
|
||||
},
|
||||
"rcon-server": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/rcon-server/-/rcon-server-0.1.1.tgz",
|
||||
"integrity": "sha512-oJ9+s0yxGc7in6GBBBxFXKRY2OyIVxFsoAEHlo5iFXDCuK6O4gY4qJ9XndMBVmA+nABkyOrN6QAFzoE6wZiI7A=="
|
||||
},
|
||||
"readdirp": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
||||
|
@ -13,6 +13,7 @@
|
||||
"mongodb": "^4.8.0",
|
||||
"node-kcp-token": "github:memetrollsxd/node-kcp",
|
||||
"protobufjs": "^7.0.0",
|
||||
"rcon-server": "^0.1.1",
|
||||
"typescript": "^4.7.4"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,22 +27,14 @@ export default class Interface {
|
||||
|
||||
private constructor() { }
|
||||
|
||||
public static readonly start = () => {
|
||||
public static start() {
|
||||
Interface.rl.question("", (_command) => {
|
||||
if (!_command) {
|
||||
Interface.start();
|
||||
return;
|
||||
}
|
||||
const cmd = new Command(_command);
|
||||
import(`./${alias[cmd.name] || cmd.name}`).then(async module => {
|
||||
await module.default(cmd);
|
||||
}).catch(err => {
|
||||
if (err.code == "MODULE_NOT_FOUND") {
|
||||
c.log(`Command ${cmd.name} not found.`);
|
||||
return;
|
||||
}
|
||||
c.error(err);
|
||||
});
|
||||
Interface.handle(cmd);
|
||||
Interface.start();
|
||||
});
|
||||
|
||||
@ -51,4 +43,16 @@ export default class Interface {
|
||||
process.exit(0);
|
||||
});
|
||||
}
|
||||
|
||||
public static handle(cmd: Command) {
|
||||
import(`./${alias[cmd.name] || cmd.name}`).then(async module => {
|
||||
await module.default(cmd);
|
||||
}).catch(err => {
|
||||
if (err.code == "MODULE_NOT_FOUND") {
|
||||
c.log(`Command ${cmd.name} not found.`);
|
||||
return;
|
||||
}
|
||||
c.error(err);
|
||||
});
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@
|
||||
import Interface from "./commands/Interface";
|
||||
import HttpServer from "./http/HttpServer";
|
||||
import SRServer from "./server/kcp/SRServer";
|
||||
import RCONServer from "./server/rcon/RCONServer";
|
||||
import Banners from "./util/Banner";
|
||||
import Logger from "./util/Logger";
|
||||
import ProtoFactory from "./util/ProtoFactory"
|
||||
@ -15,6 +16,7 @@ c.log(`Starting CrepeSR...`);
|
||||
|
||||
Banners.init();
|
||||
ProtoFactory.init();
|
||||
Interface.start();
|
||||
Interface.start();
|
||||
HttpServer.getInstance().start();
|
||||
SRServer.getInstance().start();
|
||||
SRServer.getInstance().start();
|
||||
RCONServer.getInstance().start();
|
54
src/server/rcon/RCONServer.ts
Normal file
54
src/server/rcon/RCONServer.ts
Normal file
@ -0,0 +1,54 @@
|
||||
// @ts-ignore
|
||||
import { RCONServer as RServer } from "rcon-server";
|
||||
import { Writable } from "stream";
|
||||
import Interface, { Command } from "../../commands/Interface";
|
||||
import Config from "../../util/Config";
|
||||
import Logger from "../../util/Logger";
|
||||
const c = new Logger("RCON", "green");
|
||||
|
||||
export default class RCONServer {
|
||||
private static _instance: RCONServer;
|
||||
public RCON!: RServer;
|
||||
|
||||
private constructor() { }
|
||||
|
||||
public static getInstance(): RCONServer {
|
||||
if (!this._instance) this._instance = new RCONServer();
|
||||
return this._instance;
|
||||
}
|
||||
|
||||
public start() {
|
||||
if (!Config.RCON.RCON_ENABLED) return;
|
||||
this.RCON = new RServer({
|
||||
host: Config.HTTP.HTTP_HOST,
|
||||
clientLimit: Config.RCON.RCON_CLIENT_LIMIT,
|
||||
destroySocketOnLimitExceeded: false,
|
||||
emitAdvancedEvents: false,
|
||||
password: Config.RCON.RCON_PASSWORD,
|
||||
port: Config.RCON.RCON_PORT
|
||||
});
|
||||
|
||||
this.RCON.on("listening", () => {
|
||||
c.log(`Listening on ${Config.RCON.RCON_PORT}`);
|
||||
});
|
||||
|
||||
this.RCON.on("commandRequest", (cmd: {
|
||||
size: number,
|
||||
id: number,
|
||||
type: number,
|
||||
body: string
|
||||
resolve: (value: string) => void,
|
||||
}) => {
|
||||
c.verbL(cmd);
|
||||
Interface.handle(new Command(cmd.body));
|
||||
cmd.resolve(`Command executed.`);
|
||||
});
|
||||
|
||||
this.RCON.on("login", ({ pw, fail }: { pw: string, fail: boolean }) => {
|
||||
c.debug(pw);
|
||||
fail ? c.log(`Login failed`) : c.log(`Login successful`); // For some reason succ is flipped
|
||||
});
|
||||
|
||||
this.RCON.connect();
|
||||
}
|
||||
}
|
263
src/server/rcon/rcon-server.d.ts
vendored
Normal file
263
src/server/rcon/rcon-server.d.ts
vendored
Normal file
@ -0,0 +1,263 @@
|
||||
/** Declaration file generated by dts-gen */
|
||||
import { EventEmitter } from "events";
|
||||
|
||||
declare module "rcon-server" {
|
||||
export class RCONServer extends EventEmitter {
|
||||
constructor(obj: {
|
||||
port: number = 3839,
|
||||
host: string = "127.0.0.1",
|
||||
password: string = "password",
|
||||
clientLimit: number = 1,
|
||||
destroySocketOnLimitExceeded: boolean = true,
|
||||
emitAdvancedEvents: boolean = false
|
||||
});
|
||||
|
||||
connect(...args: any[]): void;
|
||||
|
||||
getConnectedSockets(...args: any[]): void;
|
||||
|
||||
getServerSettings(...args: any[]): void;
|
||||
|
||||
getSocketServer(...args: any[]): void;
|
||||
|
||||
static captureRejectionSymbol: any;
|
||||
|
||||
static captureRejections: boolean;
|
||||
|
||||
static defaultMaxListeners: number;
|
||||
|
||||
static errorMonitor: any;
|
||||
|
||||
static getEventListeners(emitterOrTarget: any, type: any): any;
|
||||
|
||||
static init(opts: any): void;
|
||||
|
||||
static kMaxEventTargetListeners: any;
|
||||
|
||||
static kMaxEventTargetListenersWarned: any;
|
||||
|
||||
static listenerCount(emitter: any, type: any): any;
|
||||
|
||||
static on(emitter: any, event: any, options: any): any;
|
||||
|
||||
static once(emitter: any, name: any, options: any): any;
|
||||
|
||||
static setMaxListeners(n: any, eventTargets: any): void;
|
||||
|
||||
static usingDomains: boolean;
|
||||
|
||||
}
|
||||
|
||||
export namespace RCONServer {
|
||||
class EventEmitter {
|
||||
constructor(opts: any);
|
||||
|
||||
addListener(type: any, listener: any): any;
|
||||
|
||||
emit(type: any, args: any): any;
|
||||
|
||||
eventNames(): any;
|
||||
|
||||
getMaxListeners(): any;
|
||||
|
||||
listenerCount(type: any): any;
|
||||
|
||||
listeners(type: any): any;
|
||||
|
||||
off(type: any, listener: any): any;
|
||||
|
||||
on(type: any, listener: any): any;
|
||||
|
||||
once(type: any, listener: any): any;
|
||||
|
||||
prependListener(type: any, listener: any): any;
|
||||
|
||||
prependOnceListener(type: any, listener: any): any;
|
||||
|
||||
rawListeners(type: any): any;
|
||||
|
||||
removeAllListeners(type: any, ...args: any[]): any;
|
||||
|
||||
removeListener(type: any, listener: any): any;
|
||||
|
||||
setMaxListeners(n: any): any;
|
||||
|
||||
static EventEmitter: any;
|
||||
|
||||
static captureRejectionSymbol: any;
|
||||
|
||||
static captureRejections: boolean;
|
||||
|
||||
static defaultMaxListeners: number;
|
||||
|
||||
static errorMonitor: any;
|
||||
|
||||
static getEventListeners(emitterOrTarget: any, type: any): any;
|
||||
|
||||
static init(opts: any): void;
|
||||
|
||||
static kMaxEventTargetListeners: any;
|
||||
|
||||
static kMaxEventTargetListenersWarned: any;
|
||||
|
||||
static listenerCount(emitter: any, type: any): any;
|
||||
|
||||
static on(emitter: any, event: any, options: any): any;
|
||||
|
||||
static once(emitter: any, name: any, options: any): any;
|
||||
|
||||
static setMaxListeners(n: any, eventTargets: any): void;
|
||||
|
||||
static usingDomains: boolean;
|
||||
|
||||
}
|
||||
|
||||
class EventEmitterAsyncResource {
|
||||
constructor(...args: any[]);
|
||||
|
||||
emit(...args: any[]): void;
|
||||
|
||||
emitDestroy(...args: any[]): void;
|
||||
|
||||
static EventEmitterAsyncResource: any;
|
||||
|
||||
static captureRejectionSymbol: any;
|
||||
|
||||
static captureRejections: boolean;
|
||||
|
||||
static defaultMaxListeners: number;
|
||||
|
||||
static errorMonitor: any;
|
||||
|
||||
static getEventListeners(emitterOrTarget: any, type: any): any;
|
||||
|
||||
static init(opts: any): void;
|
||||
|
||||
static kMaxEventTargetListeners: any;
|
||||
|
||||
static kMaxEventTargetListenersWarned: any;
|
||||
|
||||
static listenerCount(emitter: any, type: any): any;
|
||||
|
||||
static on(emitter: any, event: any, options: any): any;
|
||||
|
||||
static once(emitter: any, name: any, options: any): any;
|
||||
|
||||
static setMaxListeners(n: any, eventTargets: any): void;
|
||||
|
||||
static usingDomains: boolean;
|
||||
|
||||
}
|
||||
|
||||
namespace EventEmitter {
|
||||
class EventEmitterAsyncResource {
|
||||
constructor(...args: any[]);
|
||||
|
||||
emit(...args: any[]): void;
|
||||
|
||||
emitDestroy(...args: any[]): void;
|
||||
|
||||
static EventEmitter: any;
|
||||
|
||||
static EventEmitterAsyncResource: any;
|
||||
|
||||
static captureRejectionSymbol: any;
|
||||
|
||||
static captureRejections: boolean;
|
||||
|
||||
static defaultMaxListeners: number;
|
||||
|
||||
static errorMonitor: any;
|
||||
|
||||
static getEventListeners(emitterOrTarget: any, type: any): any;
|
||||
|
||||
static init(opts: any): void;
|
||||
|
||||
static kMaxEventTargetListeners: any;
|
||||
|
||||
static kMaxEventTargetListenersWarned: any;
|
||||
|
||||
static listenerCount(emitter: any, type: any): any;
|
||||
|
||||
static on(emitter: any, event: any, options: any): any;
|
||||
|
||||
static once(emitter: any, name: any, options: any): any;
|
||||
|
||||
static setMaxListeners(n: any, eventTargets: any): void;
|
||||
|
||||
static usingDomains: boolean;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace EventEmitterAsyncResource {
|
||||
class EventEmitter {
|
||||
constructor(opts: any);
|
||||
|
||||
addListener(type: any, listener: any): any;
|
||||
|
||||
emit(type: any, args: any): any;
|
||||
|
||||
eventNames(): any;
|
||||
|
||||
getMaxListeners(): any;
|
||||
|
||||
listenerCount(type: any): any;
|
||||
|
||||
listeners(type: any): any;
|
||||
|
||||
off(type: any, listener: any): any;
|
||||
|
||||
on(type: any, listener: any): any;
|
||||
|
||||
once(type: any, listener: any): any;
|
||||
|
||||
prependListener(type: any, listener: any): any;
|
||||
|
||||
prependOnceListener(type: any, listener: any): any;
|
||||
|
||||
rawListeners(type: any): any;
|
||||
|
||||
removeAllListeners(type: any, ...args: any[]): any;
|
||||
|
||||
removeListener(type: any, listener: any): any;
|
||||
|
||||
setMaxListeners(n: any): any;
|
||||
|
||||
static EventEmitter: any;
|
||||
|
||||
static EventEmitterAsyncResource: any;
|
||||
|
||||
static captureRejectionSymbol: any;
|
||||
|
||||
static captureRejections: boolean;
|
||||
|
||||
static defaultMaxListeners: number;
|
||||
|
||||
static errorMonitor: any;
|
||||
|
||||
static getEventListeners(emitterOrTarget: any, type: any): any;
|
||||
|
||||
static init(opts: any): void;
|
||||
|
||||
static kMaxEventTargetListeners: any;
|
||||
|
||||
static kMaxEventTargetListenersWarned: any;
|
||||
|
||||
static listenerCount(emitter: any, type: any): any;
|
||||
|
||||
static on(emitter: any, event: any, options: any): any;
|
||||
|
||||
static once(emitter: any, name: any, options: any): any;
|
||||
|
||||
static setMaxListeners(n: any, eventTargets: any): void;
|
||||
|
||||
static usingDomains: boolean;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -28,6 +28,12 @@ const DEFAULT_CONFIG = {
|
||||
MAINTENANCE: false,
|
||||
MAINTENANCE_MSG: "Server is in maintenance mode."
|
||||
},
|
||||
RCON: {
|
||||
RCON_ENABLED: false,
|
||||
RCON_PASSWORD: "password",
|
||||
RCON_PORT: 22103,
|
||||
RCON_CLIENT_LIMIT: 1
|
||||
},
|
||||
AUTO_ACCOUNT: false
|
||||
}
|
||||
type DefaultConfig = typeof DEFAULT_CONFIG;
|
||||
@ -82,6 +88,12 @@ export default class Config {
|
||||
MAINTENANCE_MSG: string;
|
||||
} = Config.config.GAMESERVER;
|
||||
public static AUTO_ACCOUNT: boolean = Config.config.AUTO_ACCOUNT;
|
||||
public static RCON: {
|
||||
RCON_ENABLED: boolean;
|
||||
RCON_PASSWORD: string;
|
||||
RCON_PORT: number;
|
||||
RCON_CLIENT_LIMIT: number;
|
||||
} = Config.config.RCON;
|
||||
|
||||
private constructor() { }
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user