@jsprismarine/client
Version:
Minecraft: Bedrock Edition RakNet client
174 lines (173 loc) • 21.7 kB
JavaScript
"use strict";
Object.defineProperties(exports, {
__esModule: { value: true },
[Symbol.toStringTag]: { value: "Module" }
});
const require_runtime = require("./_virtual/_rolldown/runtime.cjs.cjs");
const require_set_interval_async = require("./node_modules/.pnpm/set-interval-async@3.0.3/node_modules/set-interval-async/dist/dynamic/set-interval-async2.cjs.cjs");
let _jsprismarine_logger = require("@jsprismarine/logger");
let _jsprismarine_prismarine = require("@jsprismarine/prismarine");
let _jsprismarine_raknet = require("@jsprismarine/raknet");
let node_crypto = require("node:crypto");
node_crypto = require_runtime.__toESM(node_crypto, 1);
let node_dgram = require("node:dgram");
node_dgram = require_runtime.__toESM(node_dgram, 1);
let node_events = require("node:events");
//#region src/index.ts
var getRandomInt = (min, max) => {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
};
var PROTOCOL = 10;
var DEF_MTU_SIZE = 1455;
var RAKNET_TICK_LENGTH = 1 / 100;
var Client = class extends node_events.EventEmitter {
clientGUID = node_crypto.default.randomBytes(8).readBigInt64BE();
logger = new _jsprismarine_logger.Logger();
address;
targetAddress;
connection = null;
socket = node_dgram.default.createSocket({ type: "udp4" });
get closed() {
return false;
}
connecting = false;
connected = false;
offlineHandled = false;
loginHandled = false;
constructor() {
super();
this.address = new _jsprismarine_raknet.InetAddress("0.0.0.0", getRandomInt(46e3, 49999));
this.socket.bind(this.address.getPort(), this.address.getAddress());
}
/**
* Creates a packet listener on given address and port.
* @param {string} address - The address to listen on.
* @param {number} port - The port to listen on.
* @returns {Promise<Client>} The client instance.
* @public
*/
async connect(address = "0.0.0.0", port = 19132) {
this.targetAddress = new _jsprismarine_raknet.InetAddress(address, port);
this.socket.on("message", (buffer) => {
this.handle(buffer);
});
if (this.connection) throw new Error("Already connected/connecting to server.");
this.logger.info("JSPrismarine client is now attempting to connect...");
const timer = (0, require_set_interval_async.import_set_interval_async.setIntervalAsync)(async () => {
if (this.closed) {
await (0, require_set_interval_async.import_clear_interval_async.clearIntervalAsync)(timer);
return;
}
if (!this.connecting) {
const pk = new _jsprismarine_raknet.Protocol.UnconnectedPing();
pk.timestamp = BigInt(Date.now());
pk.encode();
await this.sendBuffer(pk.getBuffer());
}
if (this.connected && !this.loginHandled) {
const pk = new _jsprismarine_prismarine.Protocol.Packets.LoginPacket();
pk.encode();
const sendPk = new _jsprismarine_raknet.Protocol.Frame();
sendPk.reliability = 0;
sendPk.content = pk.getBuffer();
this.connection.sendFrame(sendPk, _jsprismarine_raknet.ConnectionPriority.NORMAL);
this.loginHandled = true;
}
this.connection?.update(Date.now());
}, RAKNET_TICK_LENGTH * 1e3);
return this;
}
/**
* Handles the incoming buffer.
* @param {Buffer} buffer - The buffer to handle.
* @private
* @internal
*/
async handle(buffer) {
const header = buffer.readUInt8();
if (this.connection && this.offlineHandled) {
this.connection.handle(buffer);
return;
}
let buf;
switch (header) {
case _jsprismarine_raknet.MessageIdentifiers.UNCONNECTED_PONG:
buf = this.handleUnconnectedPong(buffer);
await this.sendBuffer(buf);
break;
case _jsprismarine_raknet.MessageIdentifiers.OPEN_CONNECTION_REPLY_1:
buf = this.handleOpenConnectionReply1(buffer);
await this.sendBuffer(buf);
break;
case _jsprismarine_raknet.MessageIdentifiers.OPEN_CONNECTION_REPLY_2:
this.handleOpenConnectionReply2(buffer);
break;
default: this.logger.warn(`Unhandled offline packet ID: ${header}`, "Client/handle");
}
}
handleUnconnectedPong(buffer) {
const decodedPacket = new _jsprismarine_raknet.Protocol.UnconnectedPong(buffer);
decodedPacket.decode();
if (!decodedPacket.isValid()) throw new Error("Received an invalid offline message");
const packet = new _jsprismarine_raknet.Protocol.OpenConnectionRequest1();
packet.protocol = PROTOCOL;
packet.mtuSize = DEF_MTU_SIZE;
packet.encode();
return packet.getBuffer();
}
handleOpenConnectionReply1(buffer) {
const decodedPacket = new _jsprismarine_raknet.Protocol.OpenConnectionReply1(buffer);
decodedPacket.decode();
if (!decodedPacket.isValid()) throw new Error("Received an invalid offline message");
const packet = new _jsprismarine_raknet.Protocol.OpenConnectionRequest2();
packet.serverAddress = this.targetAddress;
packet.mtuSize = DEF_MTU_SIZE;
packet.clientGUID = this.clientGUID;
packet.encode();
this.connecting = true;
this.connection = new _jsprismarine_raknet.RakNetSession(this, DEF_MTU_SIZE, {
address: this.address.getAddress(),
port: this.address.getPort(),
family: "IPv4",
size: 0
}, (0, node_crypto.randomBytes)(8).readBigInt64BE());
return packet.getBuffer();
}
handleOpenConnectionReply2(buffer) {
const decodedPacket = new _jsprismarine_raknet.Protocol.OpenConnectionReply2(buffer);
decodedPacket.decode();
if (!decodedPacket.isValid()) throw new Error("Received an invalid offline message");
const packet = new _jsprismarine_raknet.Protocol.ConnectionRequest();
packet.clientGUID = this.clientGUID;
packet.requestTimestamp = BigInt(Date.now());
packet.encode();
const sendPacket = new _jsprismarine_raknet.Protocol.Frame();
sendPacket.reliability = 0;
sendPacket.content = packet.getBuffer();
this.connection?.sendFrame(sendPacket, _jsprismarine_raknet.ConnectionPriority.NORMAL);
this.offlineHandled = true;
this.connected = true;
}
/**
* Sends the buffer to the server
*
* @param buffer
*/
async sendBuffer(buffer) {
this.socket.send(buffer, 0, buffer.byteLength, this.targetAddress.getPort(), this.targetAddress.getAddress());
}
getSocket() {
return this.socket;
}
getAddress() {
return this.address;
}
async removeConnection(_connection, _reason) {
throw new Error("Method not implemented.");
}
};
//#endregion
exports.default = Client;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguY2pzLmNqcyIsIm5hbWVzIjpbXSwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgTG9nZ2VyIH0gZnJvbSAnQGpzcHJpc21hcmluZS9sb2dnZXInO1xuaW1wb3J0IHsgUHJvdG9jb2wgYXMgSlNQUHJvdG9jb2wgfSBmcm9tICdAanNwcmlzbWFyaW5lL3ByaXNtYXJpbmUnO1xuaW1wb3J0IHsgQ29ubmVjdGlvblByaW9yaXR5LCBJbmV0QWRkcmVzcywgTWVzc2FnZUlkZW50aWZpZXJzLCBQcm90b2NvbCwgUmFrTmV0U2Vzc2lvbiB9IGZyb20gJ0Bqc3ByaXNtYXJpbmUvcmFrbmV0JztcbmltcG9ydCBDcnlwdG8sIHsgcmFuZG9tQnl0ZXMgfSBmcm9tICdub2RlOmNyeXB0byc7XG5pbXBvcnQgRGdyYW0sIHsgdHlwZSBTb2NrZXQgfSBmcm9tICdub2RlOmRncmFtJztcbmltcG9ydCB7IEV2ZW50RW1pdHRlciB9IGZyb20gJ25vZGU6ZXZlbnRzJztcbmltcG9ydCB7IGNsZWFySW50ZXJ2YWxBc3luYywgc2V0SW50ZXJ2YWxBc3luYyB9IGZyb20gJ3NldC1pbnRlcnZhbC1hc3luYy9keW5hbWljJztcblxuLy8gaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9hLzE1Mjc4MjAvMzE0MjU1M1xuY29uc3QgZ2V0UmFuZG9tSW50ID0gKG1pbjogbnVtYmVyLCBtYXg6IG51bWJlcikgPT4ge1xuICAgIG1pbiA9IE1hdGguY2VpbChtaW4pO1xuICAgIG1heCA9IE1hdGguZmxvb3IobWF4KTtcbiAgICByZXR1cm4gTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogKG1heCAtIG1pbiArIDEpKSArIG1pbjtcbn07XG5cbi8vIE1pbmVjcmFmdCByZWxhdGVkIHByb3RvY29sXG5jb25zdCBQUk9UT0NPTCA9IDEwO1xuXG4vLyBNYXggbmV0IHRyYW5zZmVyIHVuaXRcbmNvbnN0IERFRl9NVFVfU0laRSA9IDE0NTU7XG5cbi8vIFJha25ldCB0aWNrc1xuY29uc3QgUkFLTkVUX1RQUyA9IDEwMDtcbmNvbnN0IFJBS05FVF9USUNLX0xFTkdUSCA9IDEgLyBSQUtORVRfVFBTO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBDbGllbnQgZXh0ZW5kcyBFdmVudEVtaXR0ZXIge1xuICAgIHByaXZhdGUgY2xpZW50R1VJRCA9IENyeXB0by5yYW5kb21CeXRlcyg4KS5yZWFkQmlnSW50NjRCRSgpO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgbG9nZ2VyID0gbmV3IExvZ2dlcigpO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgYWRkcmVzczogSW5ldEFkZHJlc3M7XG4gICAgcHJpdmF0ZSB0YXJnZXRBZGRyZXNzITogSW5ldEFkZHJlc3M7XG4gICAgcHJpdmF0ZSBjb25uZWN0aW9uOiBSYWtOZXRTZXNzaW9uIHwgbnVsbCA9IG51bGw7XG4gICAgcHJpdmF0ZSByZWFkb25seSBzb2NrZXQgPSBEZ3JhbS5jcmVhdGVTb2NrZXQoeyB0eXBlOiAndWRwNCcgfSk7XG4gICAgcHJpdmF0ZSBnZXQgY2xvc2VkKCkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBjb25uZWN0aW5nID0gZmFsc2U7XG4gICAgcHJpdmF0ZSBjb25uZWN0ZWQgPSBmYWxzZTtcbiAgICBwcml2YXRlIG9mZmxpbmVIYW5kbGVkID0gZmFsc2U7XG4gICAgcHJpdmF0ZSBsb2dpbkhhbmRsZWQgPSBmYWxzZTtcblxuICAgIHB1YmxpYyBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgdGhpcy5hZGRyZXNzID0gbmV3IEluZXRBZGRyZXNzKCcwLjAuMC4wJywgZ2V0UmFuZG9tSW50KDQ2MDAwLCA0OTk5OSkpO1xuICAgICAgICB0aGlzLnNvY2tldC5iaW5kKHRoaXMuYWRkcmVzcy5nZXRQb3J0KCksIHRoaXMuYWRkcmVzcy5nZXRBZGRyZXNzKCkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBwYWNrZXQgbGlzdGVuZXIgb24gZ2l2ZW4gYWRkcmVzcyBhbmQgcG9ydC5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gYWRkcmVzcyAtIFRoZSBhZGRyZXNzIHRvIGxpc3RlbiBvbi5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gcG9ydCAtIFRoZSBwb3J0IHRvIGxpc3RlbiBvbi5cbiAgICAgKiBAcmV0dXJucyB7UHJvbWlzZTxDbGllbnQ+fSBUaGUgY2xpZW50IGluc3RhbmNlLlxuICAgICAqIEBwdWJsaWNcbiAgICAgKi9cbiAgICBwdWJsaWMgYXN5bmMgY29ubmVjdChhZGRyZXNzID0gJzAuMC4wLjAnLCBwb3J0ID0gMTkxMzIpOiBQcm9taXNlPENsaWVudD4ge1xuICAgICAgICB0aGlzLnRhcmdldEFkZHJlc3MgPSBuZXcgSW5ldEFkZHJlc3MoYWRkcmVzcywgcG9ydCk7XG5cbiAgICAgICAgdGhpcy5zb2NrZXQub24oJ21lc3NhZ2UnLCAoYnVmZmVyOiBCdWZmZXIpID0+IHtcbiAgICAgICAgICAgIHZvaWQgdGhpcy5oYW5kbGUoYnVmZmVyKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKHRoaXMuY29ubmVjdGlvbikgdGhyb3cgbmV3IEVycm9yKCdBbHJlYWR5IGNvbm5lY3RlZC9jb25uZWN0aW5nIHRvIHNlcnZlci4nKTtcblxuICAgICAgICB0aGlzLmxvZ2dlci5pbmZvKCdKU1ByaXNtYXJpbmUgY2xpZW50IGlzIG5vdyBhdHRlbXB0aW5nIHRvIGNvbm5lY3QuLi4nKTtcblxuICAgICAgICBjb25zdCB0aW1lciA9IHNldEludGVydmFsQXN5bmMoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuY2xvc2VkKSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgY2xlYXJJbnRlcnZhbEFzeW5jKHRpbWVyKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFNlbmQgYSBjbGllbnQgcGFja2V0IHRvIHRoZSBzZXJ2ZXJcbiAgICAgICAgICAgIC8vIHNvIHRoZSBzZXJ2ZXIgZ29lcyBpbiB0YXJnZXQgbW9kZVxuICAgICAgICAgICAgLy8gYW5kIHRoZSBsb2dpbiBwcm9jZXNzIHN0YXJ0c1xuICAgICAgICAgICAgaWYgKCF0aGlzLmNvbm5lY3RpbmcpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBwayA9IG5ldyBQcm90b2NvbC5VbmNvbm5lY3RlZFBpbmcoKTtcbiAgICAgICAgICAgICAgICBway50aW1lc3RhbXAgPSBCaWdJbnQoRGF0ZS5ub3coKSk7XG4gICAgICAgICAgICAgICAgLy8gVE9ETzogY2FuIGJlIG9taXR0ZWQuLi4gcGsuID0gdGhpcy5jbGllbnRHVUlEO1xuICAgICAgICAgICAgICAgIHBrLmVuY29kZSgpO1xuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuc2VuZEJ1ZmZlcihway5nZXRCdWZmZXIoKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmNvbm5lY3RlZCAmJiAhdGhpcy5sb2dpbkhhbmRsZWQpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBwayA9IG5ldyBKU1BQcm90b2NvbC5QYWNrZXRzLkxvZ2luUGFja2V0KCk7XG4gICAgICAgICAgICAgICAgcGsuZW5jb2RlKCk7XG5cbiAgICAgICAgICAgICAgICBjb25zdCBzZW5kUGsgPSBuZXcgUHJvdG9jb2wuRnJhbWUoKTtcbiAgICAgICAgICAgICAgICBzZW5kUGsucmVsaWFiaWxpdHkgPSAwO1xuICAgICAgICAgICAgICAgIHNlbmRQay5jb250ZW50ID0gcGsuZ2V0QnVmZmVyKCk7XG5cbiAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24hLnNlbmRGcmFtZShzZW5kUGssIENvbm5lY3Rpb25Qcmlvcml0eS5OT1JNQUwpOyAvLyBQYWNrZXQgbmVlZHMgdG8gYmUgc3BsaXR0ZWRcbiAgICAgICAgICAgICAgICB0aGlzLmxvZ2luSGFuZGxlZCA9IHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbj8udXBkYXRlKERhdGUubm93KCkpO1xuICAgICAgICB9LCBSQUtORVRfVElDS19MRU5HVEggKiAxMDAwKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlcyB0aGUgaW5jb21pbmcgYnVmZmVyLlxuICAgICAqIEBwYXJhbSB7QnVmZmVyfSBidWZmZXIgLSBUaGUgYnVmZmVyIHRvIGhhbmRsZS5cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBpbnRlcm5hbFxuICAgICAqL1xuICAgIHByaXZhdGUgYXN5bmMgaGFuZGxlKGJ1ZmZlcjogQnVmZmVyKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGNvbnN0IGhlYWRlciA9IGJ1ZmZlci5yZWFkVUludDgoKTsgLy8gUmVhZCBwYWNrZXQgaGVhZGVyXG5cbiAgICAgICAgaWYgKHRoaXMuY29ubmVjdGlvbiAmJiB0aGlzLm9mZmxpbmVIYW5kbGVkKSB7XG4gICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uaGFuZGxlKGJ1ZmZlcik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgYnVmO1xuICAgICAgICBzd2l0Y2ggKGhlYWRlcikge1xuICAgICAgICAgICAgY2FzZSBNZXNzYWdlSWRlbnRpZmllcnMuVU5DT05ORUNURURfUE9ORzpcbiAgICAgICAgICAgICAgICBidWYgPSB0aGlzLmhhbmRsZVVuY29ubmVjdGVkUG9uZyhidWZmZXIpO1xuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuc2VuZEJ1ZmZlcihidWYpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBNZXNzYWdlSWRlbnRpZmllcnMuT1BFTl9DT05ORUNUSU9OX1JFUExZXzE6XG4gICAgICAgICAgICAgICAgYnVmID0gdGhpcy5oYW5kbGVPcGVuQ29ubmVjdGlvblJlcGx5MShidWZmZXIpO1xuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuc2VuZEJ1ZmZlcihidWYpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBNZXNzYWdlSWRlbnRpZmllcnMuT1BFTl9DT05ORUNUSU9OX1JFUExZXzI6XG4gICAgICAgICAgICAgICAgdGhpcy5oYW5kbGVPcGVuQ29ubmVjdGlvblJlcGx5MihidWZmZXIpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICB0aGlzLmxvZ2dlci53YXJuKGBVbmhhbmRsZWQgb2ZmbGluZSBwYWNrZXQgSUQ6ICR7aGVhZGVyfWAsICdDbGllbnQvaGFuZGxlJyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgaGFuZGxlVW5jb25uZWN0ZWRQb25nKGJ1ZmZlcjogQnVmZmVyKTogQnVmZmVyIHtcbiAgICAgICAgLy8gRGVjb2RlIHNlcnZlciBwYWNrZXRcbiAgICAgICAgY29uc3QgZGVjb2RlZFBhY2tldCA9IG5ldyBQcm90b2NvbC5VbmNvbm5lY3RlZFBvbmcoYnVmZmVyKTtcbiAgICAgICAgZGVjb2RlZFBhY2tldC5kZWNvZGUoKTtcblxuICAgICAgICAvLyBDaGVjayBwYWNrZXQgdmFsaWRpdHlcbiAgICAgICAgLy8gVG8gcmVmYWN0b3JcbiAgICAgICAgaWYgKCFkZWNvZGVkUGFja2V0LmlzVmFsaWQoKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdSZWNlaXZlZCBhbiBpbnZhbGlkIG9mZmxpbmUgbWVzc2FnZScpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRW5jb2RlIHJlc3BvbnNlXG4gICAgICAgIGNvbnN0IHBhY2tldCA9IG5ldyBQcm90b2NvbC5PcGVuQ29ubmVjdGlvblJlcXVlc3QxKCk7XG4gICAgICAgIHBhY2tldC5wcm90b2NvbCA9IFBST1RPQ09MO1xuICAgICAgICBwYWNrZXQubXR1U2l6ZSA9IERFRl9NVFVfU0laRTtcbiAgICAgICAgcGFja2V0LmVuY29kZSgpO1xuXG4gICAgICAgIC8vIFVwZGF0ZSBzZXNzaW9uIHN0YXR1c1xuICAgICAgICAvLyB0aGlzLnN0YXR1cyA9IENvbm5lY3Rpb25TdGF0dXMuVGFyZ2V0dGVkO1xuXG4gICAgICAgIHJldHVybiBwYWNrZXQuZ2V0QnVmZmVyKCk7XG4gICAgfVxuXG4gICAgcHVibGljIGhhbmRsZU9wZW5Db25uZWN0aW9uUmVwbHkxKGJ1ZmZlcjogQnVmZmVyKTogQnVmZmVyIHtcbiAgICAgICAgLy8gRGVjb2RlIHNlcnZlciBwYWNrZXRcbiAgICAgICAgY29uc3QgZGVjb2RlZFBhY2tldCA9IG5ldyBQcm90b2NvbC5PcGVuQ29ubmVjdGlvblJlcGx5MShidWZmZXIpO1xuICAgICAgICBkZWNvZGVkUGFja2V0LmRlY29kZSgpO1xuXG4gICAgICAgIC8vIENoZWNrIHBhY2tldCB2YWxpZGl0eVxuICAgICAgICAvLyBUbyByZWZhY3RvclxuICAgICAgICBpZiAoIWRlY29kZWRQYWNrZXQuaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1JlY2VpdmVkIGFuIGludmFsaWQgb2ZmbGluZSBtZXNzYWdlJyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBFbmNvZGUgcmVzcG9uc2VcbiAgICAgICAgY29uc3QgcGFja2V0ID0gbmV3IFByb3RvY29sLk9wZW5Db25uZWN0aW9uUmVxdWVzdDIoKTtcbiAgICAgICAgcGFja2V0LnNlcnZlckFkZHJlc3MgPSB0aGlzLnRhcmdldEFkZHJlc3M7XG4gICAgICAgIHBhY2tldC5tdHVTaXplID0gREVGX01UVV9TSVpFO1xuICAgICAgICBwYWNrZXQuY2xpZW50R1VJRCA9IHRoaXMuY2xpZW50R1VJRDtcbiAgICAgICAgcGFja2V0LmVuY29kZSgpO1xuXG4gICAgICAgIC8vIFVwZGF0ZSBzZXNzaW9uIHN0YXR1c1xuICAgICAgICB0aGlzLmNvbm5lY3RpbmcgPSB0cnVlO1xuICAgICAgICAvLyBUaGlzLnN0YXR1cyA9IENvbm5lY3Rpb25TdGF0dXMuQ29ubmVjdGVkO1xuICAgICAgICB0aGlzLmNvbm5lY3Rpb24gPSBuZXcgUmFrTmV0U2Vzc2lvbihcbiAgICAgICAgICAgIHRoaXMgYXMgYW55LFxuICAgICAgICAgICAgREVGX01UVV9TSVpFLFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGFkZHJlc3M6IHRoaXMuYWRkcmVzcy5nZXRBZGRyZXNzKCksXG4gICAgICAgICAgICAgICAgcG9ydDogdGhpcy5hZGRyZXNzLmdldFBvcnQoKSxcbiAgICAgICAgICAgICAgICBmYW1pbHk6ICdJUHY0JyxcbiAgICAgICAgICAgICAgICBzaXplOiAwXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcmFuZG9tQnl0ZXMoOCkucmVhZEJpZ0ludDY0QkUoKVxuICAgICAgICApO1xuXG4gICAgICAgIHJldHVybiBwYWNrZXQuZ2V0QnVmZmVyKCk7XG4gICAgfVxuXG4gICAgcHVibGljIGhhbmRsZU9wZW5Db25uZWN0aW9uUmVwbHkyKGJ1ZmZlcjogQnVmZmVyKTogdm9pZCB7XG4gICAgICAgIC8vIERlY29kZSBzZXJ2ZXIgcGFja2V0XG4gICAgICAgIGNvbnN0IGRlY29kZWRQYWNrZXQgPSBuZXcgUHJvdG9jb2wuT3BlbkNvbm5lY3Rpb25SZXBseTIoYnVmZmVyKTtcbiAgICAgICAgZGVjb2RlZFBhY2tldC5kZWNvZGUoKTtcblxuICAgICAgICAvLyBDaGVjayBwYWNrZXQgdmFsaWRpdHlcbiAgICAgICAgLy8gVG8gcmVmYWN0b3JcbiAgICAgICAgaWYgKCFkZWNvZGVkUGFja2V0LmlzVmFsaWQoKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdSZWNlaXZlZCBhbiBpbnZhbGlkIG9mZmxpbmUgbWVzc2FnZScpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRW5jb2RlIHJlc3BvbnNlIChlbmNhcHN1bGF0ZWQpXG4gICAgICAgIGNvbnN0IHBhY2tldCA9IG5ldyBQcm90b2NvbC5Db25uZWN0aW9uUmVxdWVzdCgpO1xuICAgICAgICBwYWNrZXQuY2xpZW50R1VJRCA9IHRoaXMuY2xpZW50R1VJRDtcbiAgICAgICAgcGFja2V0LnJlcXVlc3RUaW1lc3RhbXAgPSBCaWdJbnQoRGF0ZS5ub3coKSk7XG4gICAgICAgIHBhY2tldC5lbmNvZGUoKTtcblxuICAgICAgICBjb25zdCBzZW5kUGFja2V0ID0gbmV3IFByb3RvY29sLkZyYW1lKCk7XG4gICAgICAgIHNlbmRQYWNrZXQucmVsaWFiaWxpdHkgPSAwO1xuICAgICAgICBzZW5kUGFja2V0LmNvbnRlbnQgPSBwYWNrZXQuZ2V0QnVmZmVyKCk7XG5cbiAgICAgICAgdGhpcy5jb25uZWN0aW9uPy5zZW5kRnJhbWUoc2VuZFBhY2tldCwgQ29ubmVjdGlvblByaW9yaXR5Lk5PUk1BTCk7XG5cbiAgICAgICAgdGhpcy5vZmZsaW5lSGFuZGxlZCA9IHRydWU7XG4gICAgICAgIHRoaXMuY29ubmVjdGVkID0gdHJ1ZTsgLy8gU2hvdWxkIGJlLi4uIHdlIGNhbid0IHJlbHkgb24gaXRcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZW5kcyB0aGUgYnVmZmVyIHRvIHRoZSBzZXJ2ZXJcbiAgICAgKlxuICAgICAqIEBwYXJhbSBidWZmZXJcbiAgICAgKi9cbiAgICBwdWJsaWMgYXN5bmMgc2VuZEJ1ZmZlcihidWZmZXI6IEJ1ZmZlcik6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICB0aGlzLnNvY2tldC5zZW5kKFxuICAgICAgICAgICAgYnVmZmVyIGFzIGFueSxcbiAgICAgICAgICAgIDAsXG4gICAgICAgICAgICBidWZmZXIuYnl0ZUxlbmd0aCxcbiAgICAgICAgICAgIHRoaXMudGFyZ2V0QWRkcmVzcy5nZXRQb3J0KCksXG4gICAgICAgICAgICB0aGlzLnRhcmdldEFkZHJlc3MuZ2V0QWRkcmVzcygpXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcHVibGljIGdldFNvY2tldCgpOiBTb2NrZXQge1xuICAgICAgICByZXR1cm4gdGhpcy5zb2NrZXQ7XG4gICAgfVxuXG4gICAgcHVibGljIGdldEFkZHJlc3MoKTogSW5ldEFkZHJlc3Mge1xuICAgICAgICByZXR1cm4gdGhpcy5hZGRyZXNzO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyByZW1vdmVDb25uZWN0aW9uKF9jb25uZWN0aW9uOiBSYWtOZXRTZXNzaW9uLCBfcmVhc29uPzogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTWV0aG9kIG5vdCBpbXBsZW1lbnRlZC4nKTtcbiAgICB9XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7QUFTQSxJQUFNLGdCQUFnQixLQUFhLFFBQWdCO0NBQy9DLE1BQU0sS0FBSyxLQUFLLEdBQUc7Q0FDbkIsTUFBTSxLQUFLLE1BQU0sR0FBRztDQUNwQixPQUFPLEtBQUssTUFBTSxLQUFLLE9BQU8sS0FBSyxNQUFNLE1BQU0sRUFBRSxJQUFJO0FBQ3pEO0FBR0EsSUFBTSxXQUFXO0FBR2pCLElBQU0sZUFBZTtBQUlyQixJQUFNLHFCQUFxQixJQUFJO0FBRS9CLElBQXFCLFNBQXJCLGNBQW9DLFlBQUEsYUFBYTtDQUM3QyxhQUFxQixZQUFBLFFBQU8sWUFBWSxDQUFDLEVBQUUsZUFBZTtDQUMxRCxTQUEwQixJQUFJLHFCQUFBLE9BQU87Q0FDckM7Q0FDQTtDQUNBLGFBQTJDO0NBQzNDLFNBQTBCLFdBQUEsUUFBTSxhQUFhLEVBQUUsTUFBTSxPQUFPLENBQUM7Q0FDN0QsSUFBWSxTQUFTO0VBQ2pCLE9BQU87Q0FDWDtDQUVBLGFBQXFCO0NBQ3JCLFlBQW9CO0NBQ3BCLGlCQUF5QjtDQUN6QixlQUF1QjtDQUV2QixjQUFxQjtFQUNqQixNQUFNO0VBQ04sS0FBSyxVQUFVLElBQUkscUJBQUEsWUFBWSxXQUFXLGFBQWEsTUFBTyxLQUFLLENBQUM7RUFDcEUsS0FBSyxPQUFPLEtBQUssS0FBSyxRQUFRLFFBQVEsR0FBRyxLQUFLLFFBQVEsV0FBVyxDQUFDO0NBQ3RFOzs7Ozs7OztDQVNBLE1BQWEsUUFBUSxVQUFVLFdBQVcsT0FBTyxPQUF3QjtFQUNyRSxLQUFLLGdCQUFnQixJQUFJLHFCQUFB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