UNPKG

@krp-races/krp-node-wrapper

Version:

A node.js wrapper for a dedicated or challenge server in kart racing pro.

163 lines (160 loc) 6.57 kB
import { _ as __awaiter } from '../tslib.es6-WQS2tr1v.js'; import { EventEmitter } from 'events'; import { ClientStatus } from '../enums/ClientStatus.mjs'; import { SocketWrapper } from './SocketWrapper.mjs'; import { writeStringLines } from '../utils/writeStringLines.mjs'; import { readStringLines } from '../utils/readStringLines.mjs'; import { timeout } from '../utils/timeout.mjs'; import 'dgram'; class RemoteAdminClient extends EventEmitter { constructor(options) { super(); this.enabled = false; this.status = ClientStatus.NOT_CONNECTED; this.messageId = 0; this.options = options; this.socket = new SocketWrapper(options); this.socket.on("error", this.handleError.bind(this)); this.on("connected", this.handleKeepAlive.bind(this)); } setEnabled(enabled) { const prevEnabled = this.enabled; this.enabled = enabled; if (!prevEnabled && enabled) this.handleReconnect(); if (prevEnabled && !enabled) this.disconnect(); } getEnabled() { return this.enabled; } setStatus(status) { this.status = status; this.messageId = 0; } getStatus() { return this.status; } connect() { return __awaiter(this, void 0, void 0, function* () { if (this.status === ClientStatus.CONNECTED) return; this.setStatus(ClientStatus.CONNECTING); const data = writeStringLines(["CONNECT", this.options.password]); this.socket.send(data); const promise = new Promise((resolve, reject) => { const listener = (msg) => { const lines = readStringLines(msg); switch (lines[0]) { case "OK": if (lines[1] !== "krp") { reject(new Error("Wrong game")); this.setStatus(ClientStatus.NOT_CONNECTED); this.socket.removeListener("message", listener); break; } resolve(undefined); this.setStatus(ClientStatus.CONNECTED); this.socket.removeListener("message", listener); break; case "FULL": reject(new Error("Server is full")); this.setStatus(ClientStatus.NOT_CONNECTED); this.socket.removeListener("message", listener); break; case "WRONGPASSWORD": reject(new Error("Wrong password")); this.setStatus(ClientStatus.NOT_CONNECTED); this.socket.removeListener("message", listener); break; } }; this.socket.on("message", listener); }); return Promise.race([promise, timeout(5000)]).catch((err) => this.handleError(err)); }); } disconnect() { if (this.status !== ClientStatus.CONNECTED) return; const data = writeStringLines(["DISCONNECT"]); this.socket.send(data); this.setStatus(ClientStatus.NOT_CONNECTED); this.emit("disconnected"); } sendCommand(command, message) { return __awaiter(this, void 0, void 0, function* () { if (this.status !== ClientStatus.CONNECTED) return; const messageId = this.messageId; const base = ["CMD", messageId.toFixed(0), command]; if (command === "MSG") { if (!message || message === "") throw new Error("Message is required for MSG command"); base.push(message); } const data = writeStringLines(base); this.socket.send(data); // Increase message id for next command this.messageId++; const promise = new Promise((resolve) => { const listener = (msg) => { const lines = readStringLines(msg); if (lines[0] === "ACK" && parseInt(lines[1]) === messageId) { resolve(undefined); this.socket.removeListener("message", listener); } }; this.socket.on("message", listener); }); return Promise.race([promise, timeout(5000)]).catch((err) => this.handleError(err)); }); } keepAlive() { return __awaiter(this, void 0, void 0, function* () { if (this.status !== ClientStatus.CONNECTED) return; const data = writeStringLines(["KEEPALIVE"]); this.socket.send(data); const promise = new Promise((resolve) => { const listener = (msg) => { const lines = readStringLines(msg); if (lines[0] === "ALIVE") { resolve(undefined); this.socket.removeListener("message", listener); } }; this.socket.on("message", listener); }); return Promise.race([promise, timeout(5000)]).catch((err) => this.handleError(err)); }); } handleReconnect() { return __awaiter(this, void 0, void 0, function* () { // If not enabled, do not attempt to reconnect if (!this.enabled) return; yield this.connect().catch((err) => this.handleError(err)); // When connected to a server, do not attempt to reconnect if (this.status === ClientStatus.CONNECTED) { this.emit("connected"); return; } // Attempt to reconnect in x milliseconds setTimeout(this.handleReconnect.bind(this), 5000); }); } handleKeepAlive() { return __awaiter(this, void 0, void 0, function* () { if (this.status !== ClientStatus.CONNECTED) return; yield this.keepAlive().catch((err) => this.handleError(err)); setTimeout(this.handleKeepAlive.bind(this), 15000); }); } handleError(err) { this.emit("error", err); this.disconnect(); } } export { RemoteAdminClient };