@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
JavaScript
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 };