mudb
Version:
Real-time database for multiplayer games
171 lines • 6.31 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const protocol_1 = require("./protocol");
const logger_1 = require("./logger");
const noop = function () { };
class MuRemoteServer {
constructor() {
this.message = {};
this.sendRaw = noop;
}
}
exports.MuRemoteServer = MuRemoteServer;
class MuClientProtocolSpec {
constructor() {
this.messageHandlers = {};
this.rawHandler = noop;
this.readyHandler = noop;
this.closeHandler = noop;
}
}
exports.MuClientProtocolSpec = MuClientProtocolSpec;
class MuClientProtocol {
constructor(schema, client, protocolSpec) {
this.configured = false;
this.schema = schema;
this.client = client;
this.server = new MuRemoteServer();
this._protocolSpec = protocolSpec;
}
configure(spec) {
if (this.configured) {
throw new Error('mudb: protocol has been configured');
}
this.configured = true;
this._protocolSpec.messageHandlers = spec.message;
this._protocolSpec.rawHandler = spec.raw || noop;
this._protocolSpec.readyHandler = spec.ready || noop;
this._protocolSpec.closeHandler = spec.close || noop;
}
}
exports.MuClientProtocol = MuClientProtocol;
class MuClient {
constructor(socket, logger, skipProtocolValidation) {
this.protocols = [];
this._protocolSpecs = [];
this.running = false;
this._started = false;
this._closed = false;
this.bandwidth = [];
this._socket = socket;
this.sessionId = socket.sessionId;
this.logger = logger || logger_1.MuDefaultLogger;
this._shouldValidateProtocol = !skipProtocolValidation;
}
start(spec_) {
if (this._started || this._closed) {
throw new Error('mudb: client has been started');
}
this._started = true;
const clientSchemas = this.protocols.map((p) => p.schema.client);
const clientFactory = new protocol_1.MuProtocolFactory(clientSchemas);
const serverSchemas = this.protocols.map((p) => p.schema.server);
const serverFactory = new protocol_1.MuProtocolFactory(serverSchemas);
const spec = spec_ || {};
const checkProtocolConsistency = (packet) => {
try {
const data = JSON.parse(packet);
if (data.clientJsonStr !== clientFactory.jsonStr ||
data.serverJsonStr !== serverFactory.jsonStr) {
this.logger.error('protocol mismatch');
this._socket.close();
}
}
catch (e) {
this.logger.exception(e);
this._socket.close();
}
};
const parser = clientFactory.createParser(this._protocolSpecs, this.logger, this.bandwidth, this.sessionId);
let validationPacket = this._shouldValidateProtocol;
this._socket.open({
ready: () => {
this.running = true;
if (this._shouldValidateProtocol) {
this._socket.send(JSON.stringify({
clientJsonStr: clientFactory.jsonStr,
serverJsonStr: serverFactory.jsonStr,
}));
}
serverFactory.protocolFactories.forEach((factory, protocolId) => {
this.bandwidth[protocolId] = {
[this.sessionId]: {
sent: {
raw: {
count: 0,
bytes: 0,
},
},
received: {
raw: {
count: 0,
bytes: 0,
},
},
},
};
const protocol = this.protocols[protocolId];
protocol.server.message = factory.createDispatch([this._socket], this.bandwidth[protocolId]);
protocol.server.sendRaw = factory.createSendRaw([this._socket], this.bandwidth[protocolId]);
});
this._protocolSpecs.forEach((protoSpec) => {
protoSpec.readyHandler();
});
if (spec.ready) {
try {
spec.ready();
}
catch (e) {
this.logger.exception(e);
}
}
},
message: (data, unreliable) => {
if (!validationPacket) {
try {
parser(data, unreliable);
}
catch (e) {
this.logger.exception(e);
}
}
else {
checkProtocolConsistency(data);
validationPacket = false;
}
},
close: (error) => {
this.running = false;
this._closed = true;
this._protocolSpecs.forEach((protoSpec) => protoSpec.closeHandler());
if (spec.close) {
try {
spec.close(error);
}
catch (e) {
this.logger.exception(e);
}
}
},
});
}
destroy() {
if (!this.running) {
throw new Error('mudb: client is not running');
}
this._socket.close();
}
protocol(schema) {
if (this._started || this._closed) {
throw new Error('mudb: attempt to register protocol after client has been started');
}
this.logger.log(`register ${schema.name} protocol`);
const spec = new MuClientProtocolSpec();
const p = new MuClientProtocol(schema, this, spec);
this.protocols.push(p);
this._protocolSpecs.push(spec);
return p;
}
}
exports.MuClient = MuClient;
//# sourceMappingURL=client.js.map