UNPKG

@krp-races/krp-node-wrapper

Version:

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

191 lines (188 loc) 8 kB
var tslib_es6 = require('../tslib.es6-DGH0njpN.js'); var events = require('events'); var modules_SocketWrapper = require('./SocketWrapper.js'); var enums_ClientStatus = require('../enums/ClientStatus.js'); var utils_readStringLines = require('../utils/readStringLines.js'); var utils_writeStringLines = require('../utils/writeStringLines.js'); var utils_timeout = require('../utils/timeout.js'); var modules_LivetimingReader = require('./LivetimingReader.js'); require('dgram'); require('../enums/DataType.js'); require('../enums/Event/ChallengeType.js'); require('../enums/Event/EventType.js'); require('../enums/Session/Classification/KartStatus.js'); require('../enums/Session/Classification/RaceStatus.js'); require('../enums/Session/SessionEntry/DriverStatusReason.js'); require('../enums/Session/SessionEntry/DriverStatusState.js'); require('../enums/Session/SessionState.js'); require('../enums/Session/SessionType.js'); require('../utils/Vec2.js'); require('../utils/Vec3.js'); const defaultData = { entries: new Map(), sessions: new Map(), contacts: [], }; class LivetimingClient extends events.EventEmitter { constructor(options) { super(); this.data = defaultData; this.enabled = false; this.status = enums_ClientStatus.ClientStatus.NOT_CONNECTED; this.options = options; this.socket = new modules_SocketWrapper.SocketWrapper(options); this.socket.on("message", this.handleMessage.bind(this)); 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; } getStatus() { return this.status; } connect() { return tslib_es6.__awaiter(this, void 0, void 0, function* () { if (this.status === enums_ClientStatus.ClientStatus.CONNECTED) return; this.setStatus(enums_ClientStatus.ClientStatus.CONNECTING); const data = utils_writeStringLines.writeStringLines(["CONNECT", this.options.password]); this.socket.send(data); const promise = new Promise((resolve, reject) => { const listener = (msg) => { const lines = utils_readStringLines.readStringLines(msg); switch (lines[0]) { case "OK": if (lines[1] !== "krp") { reject(new Error("Wrong game")); this.setStatus(enums_ClientStatus.ClientStatus.NOT_CONNECTED); this.socket.removeListener("message", listener); break; } resolve(undefined); this.setStatus(enums_ClientStatus.ClientStatus.CONNECTED); this.socket.removeListener("message", listener); break; case "FULL": reject(new Error("Server is full")); this.setStatus(enums_ClientStatus.ClientStatus.NOT_CONNECTED); this.socket.removeListener("message", listener); break; case "WRONGPASSWORD": reject(new Error("Wrong password")); this.setStatus(enums_ClientStatus.ClientStatus.NOT_CONNECTED); this.socket.removeListener("message", listener); break; } }; this.socket.on("message", listener); }); return Promise.race([promise, utils_timeout.timeout(5000)]).catch((err) => this.handleError(err)); }); } disconnect() { if (this.status !== enums_ClientStatus.ClientStatus.CONNECTED) return; const data = utils_writeStringLines.writeStringLines(["DISCONNECT"]); this.socket.send(data); this.setStatus(enums_ClientStatus.ClientStatus.NOT_CONNECTED); this.emit("disconnected"); } keepAlive() { return tslib_es6.__awaiter(this, void 0, void 0, function* () { if (this.status !== enums_ClientStatus.ClientStatus.CONNECTED) return; const data = utils_writeStringLines.writeStringLines(["KEEPALIVE"]); this.socket.send(data); const promise = new Promise((resolve) => { const listener = (msg) => { const lines = utils_readStringLines.readStringLines(msg); if (lines[0] === "ALIVE") { resolve(undefined); this.socket.removeListener("message", listener); } }; this.socket.on("message", listener); }); return Promise.race([promise, utils_timeout.timeout(5000)]).catch((err) => this.handleError(err)); }); } start(trackPositions, collisions) { if (this.status !== enums_ClientStatus.ClientStatus.CONNECTED) return; const data = utils_writeStringLines.writeStringLines([ "START", trackPositions.toFixed(0), collisions.toFixed(0), ]); this.socket.send(data); } acknowledge(messageId) { if (this.status !== enums_ClientStatus.ClientStatus.CONNECTED) return; const data = utils_writeStringLines.writeStringLines(["ACK", messageId]); this.socket.send(data); } handleReconnect() { return tslib_es6.__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 === enums_ClientStatus.ClientStatus.CONNECTED) { this.emit("connected"); this.start(this.options.trackPositions, this.options.collisions); return; } // Attempt to reconnect in x milliseconds setTimeout(this.handleReconnect.bind(this), 5000); }); } handleKeepAlive() { return tslib_es6.__awaiter(this, void 0, void 0, function* () { if (this.status !== enums_ClientStatus.ClientStatus.CONNECTED) return; yield this.keepAlive().catch((err) => this.handleError(err)); setTimeout(this.handleKeepAlive.bind(this), 15000); }); } handleMessage(msg) { if (this.status !== enums_ClientStatus.ClientStatus.CONNECTED) return; const lines = utils_readStringLines.readStringLines(msg); switch (lines[0]) { case "MSG": { const reader = new modules_LivetimingReader.LivetimingReader(lines, this.data); this.data = reader.read(); this.acknowledge(lines[1]); this.emit("data", this.data); } break; case "DATA": { const reader = new modules_LivetimingReader.LivetimingReader(lines, this.data, 1); this.data = reader.read(); this.emit("data", this.data); } break; } } handleError(err) { this.emit("error", err); this.disconnect(); } } exports.LivetimingClient = LivetimingClient;