UNPKG

@jsprismarine/prismarine

Version:

Dedicated Minecraft Bedrock Edition server written in TypeScript

398 lines (397 loc) 39.1 kB
"use strict"; Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); require("../_virtual/_rolldown/runtime.cjs.cjs"); const require_world_Position = require("../world/Position.cjs.cjs"); const require_network_packet_AddActorPacket = require("../network/packet/AddActorPacket.cjs.cjs"); const require_network_packet_MoveActorAbsolutePacket = require("../network/packet/MoveActorAbsolutePacket.cjs.cjs"); const require_network_packet_RemoveActorPacket = require("../network/packet/RemoveActorPacket.cjs.cjs"); const require_network_type_TextType = require("../network/type/TextType.cjs.cjs"); const require_utils_UUID = require("../utils/UUID.cjs.cjs"); const require_entity_Attribute = require("./Attribute.cjs.cjs"); const require_entity_Metadata = require("./Metadata.cjs.cjs"); let _jsprismarine_math = require("@jsprismarine/math"); //#region src/entity/Entity.ts /** * Entity-like class. * @class * @internal */ var EntityLike = class extends require_world_Position.Position { uuid; runtimeId; server; pitch; yaw; headYaw; /** * EntityLike constructor. * @param {object} options - The entity-like options. * @param {string} options.uuid - The entity's runtime id. * @param {bigint} options.runtimeId - The entity's runtime id. * @param {Server} options.server - The server instance. * @param {World} [options.world] - The world the entity belongs to. * @param {number} [options.pitch=0] - The pitch. * @param {number} [options.yaw=0] - The yaw. * @param {number} [options.headYaw=0] - The head yaw. * @returns {EntityLike} The entity-like instance. */ constructor({ uuid, runtimeId, pitch = 0, yaw = 0, headYaw = 0, ...options }) { super(0, 0, 0, options.world); this.uuid = uuid ?? require_utils_UUID.default.randomString(); this.runtimeId = runtimeId; this.server = options.server; this.pitch = pitch; this.yaw = yaw; this.headYaw = headYaw; } /** * Get the entity's runtime id. * @returns {bigint} The entity's runtime id. */ getRuntimeId() { return this.runtimeId; } /** * Get the server instance. * @returns {Server} The server instance. */ getServer() { return this.server; } /** * Get the entity's position. * @returns {Vector3} The entity's position. * @example * ```typescript * const position = entity.getPosition(); * ``` */ getPosition() { return new _jsprismarine_math.Vector3(this.getX(), this.getY(), this.getZ()); } /** * Returns the nearest entity from the current entity. * @todo Customizable radius * @param {Entity[]} [entities=this.getWorld().getEntities()] - The entities to compare the distance between. * @returns {Entity[]} The nearest entity. * @example * ```typescript * const nearestEntity = entity.getNearestEntity(); * console.log('Nearest entity:', nearestEntity); * ``` */ getNearestEntity(entities = this.getWorld().getEntities()) { const position = new _jsprismarine_math.Vector3(this.getX(), this.getY(), this.getZ()); const distance = (a, b) => Math.hypot(b.getX() - a.getX(), b.getY() - a.getY(), b.getZ() - a.getZ()); const closest = (target, points, eps = 1e-5) => { const distances = points.map((e) => distance(target, new _jsprismarine_math.Vector3(e.getX(), e.getY(), e.getZ()))); const closest = Math.min(...distances); return points.find((_e, i) => distances[i] - closest < eps); }; return [closest(position, entities.filter((entity) => entity.getRuntimeId() !== this.runtimeId))]; } }; /** * The base class for all entities including `Player`. * @class * @public */ var Entity = class Entity extends EntityLike { /** * The global runtime id counter. * @internal */ static runtimeIdCount = 0n; /** * The entity's namespace ID. */ static MOB_ID = "jsprismarine:unknown_entity"; /** * Get the entity type. * @returns {string} The entity's namespace ID. * @example * ```typescript * const entityType = entity.getType(); * console.log(`Entity type: ${entityType}`); * ``` */ getType() { return this.constructor.MOB_ID; } /** * Entity metadata. */ metadata = new require_entity_Metadata.Metadata(); /** * Entity attributes. */ attributes = new require_entity_Attribute.Attributes(); /** * Entity constructor. * @param {object} options - The entity options. * @param {World} options.world - The world the entity belongs to. * @param {Server} options.server - The server instance. * @param {string} [options.uuid] - The entity's UUID. * @returns {Entity} The entity instance. * @example * ```typescript * const entity = new Entity({ * world: server.getWorldManager().getDefaultWorld(), * server * }); * ``` */ constructor({ world, ...options }) { Entity.runtimeIdCount += 1n; super({ world, ...options, runtimeId: Entity.runtimeIdCount }); if (world) super.setWorld(world); } get [Symbol.toStringTag]() { return `Entity(${this.toString()})`; } /** * Convert to a string representation. * @returns {string} The string. * ```typescript * console.log(entity.toString()); * ``` */ toString() { return `uuid: §a${this.getUUID()}§r, id: §a${this.getRuntimeId()}§r, name: §b${this.getName()}§r, type: §b${this.getType()}§r, ${super.toString()}`; } /** * Get the entity's runtime id. * @returns {bigint} The entity's runtime id. * @example * ```typescript * const entityId = entity.getRuntimeId(); * console.log(entityId); // Ex. Output: 1n * ``` */ getRuntimeId() { return this.runtimeId; } /** * Get the entity's UUID. * @returns {string} The entity's UUID. * ```typescript * console.log(entity.getUUID()); * ``` */ getUUID() { return this.uuid; } /** * Fired every tick from the event subscription in the constructor. * @param {number} _tick - The current world-tick. * @returns {Promise<void>} A promise that resolves when the update is complete. * @example * ```typescript * entity.update(10); * ``` */ async update(_tick) {} /** * Get the server instance. * @returns {Server} The server instance. * @example * ```typescript * const server = entity.getServer(); * // Do things with the server. * ``` */ getServer() { return this.server; } /** * Spawn the entity. * @todo `motion`, `pitch` & `yaw` is unimplemented. * @param {Player} [player] - The player to send the packet to. * @returns {Promise<void>} A promise that resolves when the entity is spawned. */ async sendSpawn(player) { const players = player ? [player] : this.getWorld().getPlayers(); const packet = new require_network_packet_AddActorPacket.default(); packet.runtimeEntityId = this.getRuntimeId(); packet.type = this.constructor.MOB_ID; packet.position = this.getPosition(); packet.motion = new _jsprismarine_math.Vector3(0, 0, 0); packet.pitch = this.pitch; packet.yaw = this.yaw; packet.headYaw = this.headYaw; packet.metadata = this.metadata; await Promise.all(players.map(async (p) => p.getNetworkSession().send(packet))); } /** * Despawn the entity. * @param {Player} [player] - The player to send the packet to, if not specified, all players in the world will receive the packet. * @returns {Promise<void>} A promise that resolves when the entity is despawned. */ async sendDespawn(player) { const players = player ? [player] : this.getWorld().getPlayers(); const packet = new require_network_packet_RemoveActorPacket.default(); packet.uniqueEntityId = this.runtimeId; await Promise.all(players.map(async (player) => player.getNetworkSession().send(packet))); } /** * Send the position to all the players in the same world. * @returns {Promise<void>} A promise that resolves when the position is sent. */ async sendPosition() { await Promise.all(this.getWorld().getPlayers().map((target) => { const packet = new require_network_packet_MoveActorAbsolutePacket.default(); packet.runtimeEntityId = this.runtimeId; packet.position = this.getPosition(); return target.getNetworkSession().send(packet); })); } /** * Send a message to an entity. * @remarks This will silently fail on non-client-controlled entities. * @param {string} message - The message. * @param {TextType} [type=TextType.Raw] - The text type. * @example Send "Hello World!" to a client: * ```typescript * entity.sendMessage('Hello World!'); * ``` */ sendMessage(message, type = require_network_type_TextType.default.Raw) { this.server.getLogger().warn(`Entity/sendMessage is not implemented: (message: ${message}, type: ${type})`); } /** * Set the `x` position. * @param {number} x - The `x` coordinate. * @param {boolean} [suppress=false] - If true, the client won't be notified about the position change. * @returns {Promise<void>} A promise that resolves when the x position is set. * @example * ```typescript * await entity.setX(10); * ``` * @remarks This method will also send the position update to the client if `suppress` is `false`. */ async setX(x, suppress = false) { super.setX.bind(this)(x); if (suppress && !this.isPlayer()) await this.sendPosition(); } /** * Set the `y` position. * @param {number} y - The `y` coordinate. * @param {boolean} [suppress=false] - If true, the client won't be notified about the position change. * @returns {Promise<void>} A promise that resolves when the y position is set. * @example * ```typescript * await entity.setY(10); * ``` * @remarks This method will also send the position update to the client if `suppress` is `false`. */ async setY(y, suppress = false) { super.setY.bind(this)(y); if (suppress && !this.isPlayer()) await this.sendPosition(); } /** * Set the `z` position. * @param {number} z - The `z` coordinate. * @param {boolean} [suppress=false] - If true, the client won't be notified about the position change. * @returns {Promise<void>} A promise that resolves when the z position is set. * @example * ```typescript * await entity.setZ(10); * ``` * @remarks This method will also send the position update to the client if `suppress` is `false`. */ async setZ(z, suppress = false) { super.setZ.bind(this)(z); if (suppress && !this.isPlayer()) await this.sendPosition(); } /** * Set the entity's position and notify the clients. * @param {object} options - The position options. * @param {Vector3} options.position - The position. * @param {number} [options.pitch] - The pitch. * @param {number} [options.yaw] - The yaw. * @param {number} [options.headYaw] - The head yaw. * @returns {Promise<void>} A promise that resolves when the position is set. */ async setPosition({ position, pitch = this.pitch, yaw = this.yaw, headYaw = this.headYaw }) { this.pitch = pitch; this.yaw = yaw; this.headYaw = headYaw; await super.setX(position.getX()); await super.setY(position.getY()); await super.setZ(position.getZ()); await this.sendPosition(); } /** * Check if the entity is a player. * @returns {boolean} `true` if the entity is player-controlled, otherwise `false`. * @example * ```typescript * if (entity.isPlayer()) { * console.log('Entity is a player'); * } else { * console.log('Entity is not a player'); * } * ``` */ isPlayer() { return false; } /** * Check if the entity is a console instance. * @returns {boolean} `true` if the entity is console-controlled, otherwise `false`. * @example * ```typescript * if (entity.isConsole()) { * console.log('Entity is a console'); * } else { * console.log('Entity is not a console'); * } * ``` */ isConsole() { return this.getRuntimeId() <= 0n; } /** * Get the entity's (potentially custom) name. * @returns {string} The entity's name without formatting (usually prefix & suffix). * @example * ```typescript * const name = entity.getName(); * console.log(`Entity name: ${name}`); * ``` */ getName() { return this.getFormattedUsername(); } /** * Set the entity's name. * @param {string} name - The name. * @example * ```typescript * entity.setName('Mr. Sheep'); * ``` */ setName(name) { this.metadata.setNameTag(name); } /** * Get the entity's formatted name. * @returns {string} The entity's formatted name (including prefix & suffix). * @example * ```typescript * const formattedName = entity.getFormattedUsername(); * console.log(`Entity formatted name: ${formattedName}`); // Entity formatted name: Sheep * ``` */ getFormattedUsername() { return this.metadata.getString(require_entity_Metadata.MetadataFlag.NAMETAG) || (this.constructor?.MOB_ID || "Unknown Entity").split(":")[1].replaceAll("_", " ").split(" ").map((word) => word[0].toUpperCase() + word.slice(1, word.length)).join(" "); } }; //#endregion exports.Entity = Entity; exports.EntityLike = EntityLike; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRW50aXR5LmNqcy5janMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vc3JjL2VudGl0eS9FbnRpdHkudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgVmVjdG9yMyB9IGZyb20gJ0Bqc3ByaXNtYXJpbmUvbWF0aCc7XG5pbXBvcnQgdHlwZSBQbGF5ZXIgZnJvbSAnLi4vUGxheWVyJztcbmltcG9ydCB0eXBlIFNlcnZlciBmcm9tICcuLi9TZXJ2ZXInO1xuaW1wb3J0IEFkZEFjdG9yUGFja2V0IGZyb20gJy4uL25ldHdvcmsvcGFja2V0L0FkZEFjdG9yUGFja2V0JztcbmltcG9ydCBNb3ZlQWN0b3JBYnNvbHV0ZVBhY2tldCBmcm9tICcuLi9uZXR3b3JrL3BhY2tldC9Nb3ZlQWN0b3JBYnNvbHV0ZVBhY2tldCc7XG5pbXBvcnQgUmVtb3ZlQWN0b3JQYWNrZXQgZnJvbSAnLi4vbmV0d29yay9wYWNrZXQvUmVtb3ZlQWN0b3JQYWNrZXQnO1xuaW1wb3J0IFRleHRUeXBlIGZyb20gJy4uL25ldHdvcmsvdHlwZS9UZXh0VHlwZSc7XG5pbXBvcnQgVVVJRCBmcm9tICcuLi91dGlscy9VVUlEJztcbmltcG9ydCB7IFBvc2l0aW9uIH0gZnJvbSAnLi4vd29ybGQvUG9zaXRpb24nO1xuaW1wb3J0IHR5cGUgeyBXb3JsZCB9IGZyb20gJy4uL3dvcmxkL1dvcmxkJztcbmltcG9ydCB7IEF0dHJpYnV0ZXMgfSBmcm9tICcuL0F0dHJpYnV0ZSc7XG5pbXBvcnQgeyBNZXRhZGF0YSwgTWV0YWRhdGFGbGFnIH0gZnJvbSAnLi9NZXRhZGF0YSc7XG5cbi8qKlxuICogRW50aXR5LWxpa2UgY2xhc3MuXG4gKiBAY2xhc3NcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgY2xhc3MgRW50aXR5TGlrZSBleHRlbmRzIFBvc2l0aW9uIHtcbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgdXVpZDogc3RyaW5nO1xuICAgIHByb3RlY3RlZCByZWFkb25seSBydW50aW1lSWQ6IGJpZ2ludDtcbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgc2VydmVyOiBTZXJ2ZXI7XG5cbiAgICBwdWJsaWMgcGl0Y2g6IG51bWJlcjtcbiAgICBwdWJsaWMgeWF3OiBudW1iZXI7XG4gICAgcHVibGljIGhlYWRZYXc6IG51bWJlcjtcblxuICAgIC8qKlxuICAgICAqIEVudGl0eUxpa2UgY29uc3RydWN0b3IuXG4gICAgICogQHBhcmFtIHtvYmplY3R9IG9wdGlvbnMgLSBUaGUgZW50aXR5LWxpa2Ugb3B0aW9ucy5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0aW9ucy51dWlkIC0gVGhlIGVudGl0eSdzIHJ1bnRpbWUgaWQuXG4gICAgICogQHBhcmFtIHtiaWdpbnR9IG9wdGlvbnMucnVudGltZUlkIC0gVGhlIGVudGl0eSdzIHJ1bnRpbWUgaWQuXG4gICAgICogQHBhcmFtIHtTZXJ2ZXJ9IG9wdGlvbnMuc2VydmVyIC0gVGhlIHNlcnZlciBpbnN0YW5jZS5cbiAgICAgKiBAcGFyYW0ge1dvcmxkfSBbb3B0aW9ucy53b3JsZF0gLSBUaGUgd29ybGQgdGhlIGVudGl0eSBiZWxvbmdzIHRvLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbb3B0aW9ucy5waXRjaD0wXSAtIFRoZSBwaXRjaC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW29wdGlvbnMueWF3PTBdIC0gVGhlIHlhdy5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW29wdGlvbnMuaGVhZFlhdz0wXSAtIFRoZSBoZWFkIHlhdy5cbiAgICAgKiBAcmV0dXJucyB7RW50aXR5TGlrZX0gVGhlIGVudGl0eS1saWtlIGluc3RhbmNlLlxuICAgICAqL1xuICAgIHB1YmxpYyBjb25zdHJ1Y3Rvcih7XG4gICAgICAgIHV1aWQsXG4gICAgICAgIHJ1bnRpbWVJZCxcbiAgICAgICAgcGl0Y2ggPSAwLFxuICAgICAgICB5YXcgPSAwLFxuICAgICAgICBoZWFkWWF3ID0gMCxcbiAgICAgICAgLi4ub3B0aW9uc1xuICAgIH06IHtcbiAgICAgICAgdXVpZD86IHN0cmluZztcbiAgICAgICAgcnVudGltZUlkOiBiaWdpbnQ7XG4gICAgICAgIHBpdGNoPzogbnVtYmVyO1xuICAgICAgICB5YXc/OiBudW1iZXI7XG4gICAgICAgIGhlYWRZYXc/OiBudW1iZXI7XG4gICAgICAgIHNlcnZlcjogU2VydmVyO1xuICAgICAgICB3b3JsZDogV29ybGQ7XG4gICAgfSkge1xuICAgICAgICBzdXBlcigwLCAwLCAwLCBvcHRpb25zLndvcmxkKTsgLy8gVE9ET1xuXG4gICAgICAgIHRoaXMudXVpZCA9IHV1aWQgPz8gVVVJRC5yYW5kb21TdHJpbmcoKTtcbiAgICAgICAgdGhpcy5ydW50aW1lSWQgPSBydW50aW1lSWQ7XG4gICAgICAgIHRoaXMuc2VydmVyID0gb3B0aW9ucy5zZXJ2ZXI7XG5cbiAgICAgICAgdGhpcy5waXRjaCA9IHBpdGNoO1xuICAgICAgICB0aGlzLnlhdyA9IHlhdztcbiAgICAgICAgdGhpcy5oZWFkWWF3ID0gaGVhZFlhdztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIGVudGl0eSdzIHJ1bnRpbWUgaWQuXG4gICAgICogQHJldHVybnMge2JpZ2ludH0gVGhlIGVudGl0eSdzIHJ1bnRpbWUgaWQuXG4gICAgICovXG4gICAgcHVibGljIGdldFJ1bnRpbWVJZCgpOiBiaWdpbnQge1xuICAgICAgICByZXR1cm4gdGhpcy5ydW50aW1lSWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IHRoZSBzZXJ2ZXIgaW5zdGFuY2UuXG4gICAgICogQHJldHVybnMge1NlcnZlcn0gVGhlIHNlcnZlciBpbnN0YW5jZS5cbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0U2VydmVyKCk6IFNlcnZlciB7XG4gICAgICAgIHJldHVybiB0aGlzLnNlcnZlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIGVudGl0eSdzIHBvc2l0aW9uLlxuICAgICAqIEByZXR1cm5zIHtWZWN0b3IzfSBUaGUgZW50aXR5J3MgcG9zaXRpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogY29uc3QgcG9zaXRpb24gPSBlbnRpdHkuZ2V0UG9zaXRpb24oKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0UG9zaXRpb24oKTogVmVjdG9yMyB7XG4gICAgICAgIHJldHVybiBuZXcgVmVjdG9yMyh0aGlzLmdldFgoKSwgdGhpcy5nZXRZKCksIHRoaXMuZ2V0WigpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBuZWFyZXN0IGVudGl0eSBmcm9tIHRoZSBjdXJyZW50IGVudGl0eS5cbiAgICAgKiBAdG9kbyBDdXN0b21pemFibGUgcmFkaXVzXG4gICAgICogQHBhcmFtIHtFbnRpdHlbXX0gW2VudGl0aWVzPXRoaXMuZ2V0V29ybGQoKS5nZXRFbnRpdGllcygpXSAtIFRoZSBlbnRpdGllcyB0byBjb21wYXJlIHRoZSBkaXN0YW5jZSBiZXR3ZWVuLlxuICAgICAqIEByZXR1cm5zIHtFbnRpdHlbXX0gVGhlIG5lYXJlc3QgZW50aXR5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIGNvbnN0IG5lYXJlc3RFbnRpdHkgPSBlbnRpdHkuZ2V0TmVhcmVzdEVudGl0eSgpO1xuICAgICAqIGNvbnNvbGUubG9nKCdOZWFyZXN0IGVudGl0eTonLCBuZWFyZXN0RW50aXR5KTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0TmVhcmVzdEVudGl0eShlbnRpdGllczogRW50aXR5W10gPSB0aGlzLmdldFdvcmxkKCkuZ2V0RW50aXRpZXMoKSk6IEVudGl0eVtdIHtcbiAgICAgICAgY29uc3QgcG9zaXRpb24gPSBuZXcgVmVjdG9yMyh0aGlzLmdldFgoKSwgdGhpcy5nZXRZKCksIHRoaXMuZ2V0WigpKTtcbiAgICAgICAgY29uc3QgZGlzdGFuY2UgPSAoYTogVmVjdG9yMywgYjogVmVjdG9yMykgPT5cbiAgICAgICAgICAgIE1hdGguaHlwb3QoYi5nZXRYKCkgLSBhLmdldFgoKSwgYi5nZXRZKCkgLSBhLmdldFkoKSwgYi5nZXRaKCkgLSBhLmdldFooKSk7XG5cbiAgICAgICAgY29uc3QgY2xvc2VzdCA9ICh0YXJnZXQ6IFZlY3RvcjMsIHBvaW50czogRW50aXR5W10sIGVwcyA9IDAuMDAwMDEpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGRpc3RhbmNlcyA9IHBvaW50cy5tYXAoKGUpID0+IGRpc3RhbmNlKHRhcmdldCwgbmV3IFZlY3RvcjMoZS5nZXRYKCksIGUuZ2V0WSgpLCBlLmdldFooKSkpKTtcbiAgICAgICAgICAgIGNvbnN0IGNsb3Nlc3QgPSBNYXRoLm1pbiguLi5kaXN0YW5jZXMpO1xuICAgICAgICAgICAgcmV0dXJuIHBvaW50cy5maW5kKChfZSwgaSkgPT4gZGlzdGFuY2VzW2ldISAtIGNsb3Nlc3QgPCBlcHMpITtcbiAgICAgICAgfTtcblxuICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgY2xvc2VzdChcbiAgICAgICAgICAgICAgICBwb3NpdGlvbixcbiAgICAgICAgICAgICAgICBlbnRpdGllcy5maWx0ZXIoKGVudGl0eSkgPT4gZW50aXR5LmdldFJ1bnRpbWVJZCgpICE9PSB0aGlzLnJ1bnRpbWVJZClcbiAgICAgICAgICAgIClcbiAgICAgICAgXTtcbiAgICB9XG59XG5cbi8qKlxuICogVGhlIGJhc2UgY2xhc3MgZm9yIGFsbCBlbnRpdGllcyBpbmNsdWRpbmcgYFBsYXllcmAuXG4gKiBAY2xhc3NcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGNsYXNzIEVudGl0eSBleHRlbmRzIEVudGl0eUxpa2Uge1xuICAgIC8qKlxuICAgICAqIFRoZSBnbG9iYWwgcnVudGltZSBpZCBjb3VudGVyLlxuICAgICAqIEBpbnRlcm5hbFxuICAgICAqL1xuICAgIHB1YmxpYyBzdGF0aWMgcnVudGltZUlkQ291bnQgPSAwbjtcblxuICAgIC8qKlxuICAgICAqIFRoZSBlbnRpdHkncyBuYW1lc3BhY2UgSUQuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIHN0YXRpYyBNT0JfSUQ6IHN0cmluZyA9ICdqc3ByaXNtYXJpbmU6dW5rbm93bl9lbnRpdHknO1xuXG4gICAgLyoqXG4gICAgICogR2V0IHRoZSBlbnRpdHkgdHlwZS5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgZW50aXR5J3MgbmFtZXNwYWNlIElELlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIGNvbnN0IGVudGl0eVR5cGUgPSBlbnRpdHkuZ2V0VHlwZSgpO1xuICAgICAqIGNvbnNvbGUubG9nKGBFbnRpdHkgdHlwZTogJHtlbnRpdHlUeXBlfWApO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHB1YmxpYyBnZXRUeXBlKCk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiAodGhpcy5jb25zdHJ1Y3RvciBhcyBhbnkpLk1PQl9JRDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBFbnRpdHkgbWV0YWRhdGEuXG4gICAgICovXG4gICAgcHVibGljIHJlYWRvbmx5IG1ldGFkYXRhID0gbmV3IE1ldGFkYXRhKCk7XG5cbiAgICAvKipcbiAgICAgKiBFbnRpdHkgYXR0cmlidXRlcy5cbiAgICAgKi9cbiAgICBwdWJsaWMgcmVhZG9ubHkgYXR0cmlidXRlcyA9IG5ldyBBdHRyaWJ1dGVzKCk7XG5cbiAgICAvKipcbiAgICAgKiBFbnRpdHkgY29uc3RydWN0b3IuXG4gICAgICogQHBhcmFtIHtvYmplY3R9IG9wdGlvbnMgLSBUaGUgZW50aXR5IG9wdGlvbnMuXG4gICAgICogQHBhcmFtIHtXb3JsZH0gb3B0aW9ucy53b3JsZCAtIFRoZSB3b3JsZCB0aGUgZW50aXR5IGJlbG9uZ3MgdG8uXG4gICAgICogQHBhcmFtIHtTZXJ2ZXJ9IG9wdGlvbnMuc2VydmVyIC0gVGhlIHNlcnZlciBpbnN0YW5jZS5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW29wdGlvbnMudXVpZF0gLSBUaGUgZW50aXR5J3MgVVVJRC5cbiAgICAgKiBAcmV0dXJucyB7RW50aXR5fSBUaGUgZW50aXR5IGluc3RhbmNlLlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIGNvbnN0IGVudGl0eSA9IG5ldyBFbnRpdHkoe1xuICAgICAqICAgICB3b3JsZDogc2VydmVyLmdldFdvcmxkTWFuYWdlcigpLmdldERlZmF1bHRXb3JsZCgpLFxuICAgICAqICAgICBzZXJ2ZXJcbiAgICAgKiB9KTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBwdWJsaWMgY29uc3RydWN0b3IoeyB3b3JsZCwgLi4ub3B0aW9ucyB9OiBPbWl0PENvbnN0cnVjdG9yUGFyYW1ldGVyczx0eXBlb2YgRW50aXR5TGlrZT5bMF0sICdydW50aW1lSWQnPikge1xuICAgICAgICBFbnRpdHkucnVudGltZUlkQ291bnQgKz0gMW47XG4gICAgICAgIHN1cGVyKHtcbiAgICAgICAgICAgIHdvcmxkLFxuICAgICAgICAgICAgLi4ub3B0aW9ucyxcbiAgICAgICAgICAgIHJ1bnRpbWVJZDogRW50aXR5LnJ1bnRpbWVJZENvdW50XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW5uZWNlc3NhcnktY29uZGl0aW9uXG4gICAgICAgIGlmICh3b3JsZCkgc3VwZXIuc2V0V29ybGQod29ybGQpO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXQgW1N5bWJvbC50b1N0cmluZ1RhZ10oKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIGBFbnRpdHkoJHt0aGlzLnRvU3RyaW5nKCl9KWA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29udmVydCB0byBhIHN0cmluZyByZXByZXNlbnRhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgc3RyaW5nLlxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiBjb25zb2xlLmxvZyhlbnRpdHkudG9TdHJpbmcoKSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgcHVibGljIHRvU3RyaW5nKCkge1xuICAgICAgICByZXR1cm4gYHV1aWQ6IMKnYSR7dGhpcy5nZXRVVUlEKCl9wqdyLCBpZDogwqdhJHt0aGlzLmdldFJ1bnRpbWVJZCgpfcKnciwgbmFtZTogwqdiJHt0aGlzLmdldE5hbWUoKX3Cp3IsIHR5cGU6IMKnYiR7dGhpcy5nZXRUeXBlKCl9wqdyLCAke3N1cGVyLnRvU3RyaW5nKCl9YDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIGVudGl0eSdzIHJ1bnRpbWUgaWQuXG4gICAgICogQHJldHVybnMge2JpZ2ludH0gVGhlIGVudGl0eSdzIHJ1bnRpbWUgaWQuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogY29uc3QgZW50aXR5SWQgPSBlbnRpdHkuZ2V0UnVudGltZUlkKCk7XG4gICAgICogY29uc29sZS5sb2coZW50aXR5SWQpOyAvLyBFeC4gT3V0cHV0OiAxblxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHB1YmxpYyBnZXRSdW50aW1lSWQoKTogYmlnaW50IHtcbiAgICAgICAgcmV0dXJuIHRoaXMucnVudGltZUlkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgZW50aXR5J3MgVVVJRC5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgZW50aXR5J3MgVVVJRC5cbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogY29uc29sZS5sb2coZW50aXR5LmdldFVVSUQoKSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgcHVibGljIGdldFVVSUQoKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudXVpZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGaXJlZCBldmVyeSB0aWNrIGZyb20gdGhlIGV2ZW50IHN1YnNjcmlwdGlvbiBpbiB0aGUgY29uc3RydWN0b3IuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IF90aWNrIC0gVGhlIGN1cnJlbnQgd29ybGQtdGljay5cbiAgICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgdXBkYXRlIGlzIGNvbXBsZXRlLlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIGVudGl0eS51cGRhdGUoMTApO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHB1YmxpYyBhc3luYyB1cGRhdGUoX3RpY2s6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge31cblxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgc2VydmVyIGluc3RhbmNlLlxuICAgICAqIEByZXR1cm5zIHtTZXJ2ZXJ9IFRoZSBzZXJ2ZXIgaW5zdGFuY2UuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogY29uc3Qgc2VydmVyID0gZW50aXR5LmdldFNlcnZlcigpO1xuICAgICAqIC8vIERvIHRoaW5ncyB3aXRoIHRoZSBzZXJ2ZXIuXG4gICAgICogYGBgXG4gICAgICovXG4gICAgcHVibGljIGdldFNlcnZlcigpOiBTZXJ2ZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5zZXJ2ZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3Bhd24gdGhlIGVudGl0eS5cbiAgICAgKiBAdG9kbyBgbW90aW9uYCwgYHBpdGNoYCAmIGB5YXdgIGlzIHVuaW1wbGVtZW50ZWQuXG4gICAgICogQHBhcmFtIHtQbGF5ZXJ9IFtwbGF5ZXJdIC0gVGhlIHBsYXllciB0byBzZW5kIHRoZSBwYWNrZXQgdG8uXG4gICAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gdGhlIGVudGl0eSBpcyBzcGF3bmVkLlxuICAgICAqL1xuICAgIHB1YmxpYyBhc3luYyBzZW5kU3Bhd24ocGxheWVyPzogUGxheWVyKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGNvbnN0IHBsYXllcnM6IFBsYXllcltdID0gcGxheWVyID8gW3BsYXllcl0gOiB0aGlzLmdldFdvcmxkKCkuZ2V0UGxheWVycygpO1xuXG4gICAgICAgIGNvbnN0IHBhY2tldCA9IG5ldyBBZGRBY3RvclBhY2tldCgpO1xuICAgICAgICBwYWNrZXQucnVudGltZUVudGl0eUlkID0gdGhpcy5nZXRSdW50aW1lSWQoKTtcbiAgICAgICAgcGFja2V0LnR5cGUgPSAodGhpcy5jb25zdHJ1Y3RvciBhcyBhbnkpLk1PQl9JRDsgLy8gVE9ET1xuICAgICAgICBwYWNrZXQucG9zaXRpb24gPSB0aGlzLmdldFBvc2l0aW9uKCk7XG4gICAgICAgIHBhY2tldC5tb3Rpb24gPSBuZXcgVmVjdG9yMygwLCAwLCAwKTsgLy8gVE9ETzogbW90aW9uXG4gICAgICAgIHBhY2tldC5waXRjaCA9IHRoaXMucGl0Y2g7XG4gICAgICAgIHBhY2tldC55YXcgPSB0aGlzLnlhdztcbiAgICAgICAgcGFja2V0LmhlYWRZYXcgPSB0aGlzLmhlYWRZYXc7XG4gICAgICAgIHBhY2tldC5tZXRhZGF0YSA9IHRoaXMubWV0YWRhdGE7XG4gICAgICAgIGF3YWl0IFByb21pc2UuYWxsKHBsYXllcnMubWFwKGFzeW5jIChwKSA9PiBwLmdldE5ldHdvcmtTZXNzaW9uKCkuc2VuZChwYWNrZXQpKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRGVzcGF3biB0aGUgZW50aXR5LlxuICAgICAqIEBwYXJhbSB7UGxheWVyfSBbcGxheWVyXSAtIFRoZSBwbGF5ZXIgdG8gc2VuZCB0aGUgcGFja2V0IHRvLCBpZiBub3Qgc3BlY2lmaWVkLCBhbGwgcGxheWVycyBpbiB0aGUgd29ybGQgd2lsbCByZWNlaXZlIHRoZSBwYWNrZXQuXG4gICAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gdGhlIGVudGl0eSBpcyBkZXNwYXduZWQuXG4gICAgICovXG4gICAgcHVibGljIGFzeW5jIHNlbmREZXNwYXduKHBsYXllcj86IFBsYXllcik6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBjb25zdCBwbGF5ZXJzOiBQbGF5ZXJbXSA9IHBsYXllciA/IFtwbGF5ZXJdIDogdGhpcy5nZXRXb3JsZCgpLmdldFBsYXllcnMoKTtcblxuICAgICAgICBjb25zdCBwYWNrZXQgPSBuZXcgUmVtb3ZlQWN0b3JQYWNrZXQoKTtcbiAgICAgICAgcGFja2V0LnVuaXF1ZUVudGl0eUlkID0gdGhpcy5ydW50aW1lSWQ7XG4gICAgICAgIGF3YWl0IFByb21pc2UuYWxsKHBsYXllcnMubWFwKGFzeW5jIChwbGF5ZXIpID0+IHBsYXllci5nZXROZXR3b3JrU2Vzc2lvbigpLnNlbmQocGFja2V0KSkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNlbmQgdGhlIHBvc2l0aW9uIHRvIGFsbCB0aGUgcGxheWVycyBpbiB0aGUgc2FtZSB3b3JsZC5cbiAgICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgcG9zaXRpb24gaXMgc2VudC5cbiAgICAgKi9cbiAgICBwdWJsaWMgYXN5bmMgc2VuZFBvc2l0aW9uKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgICAgIHRoaXMuZ2V0V29ybGQoKVxuICAgICAgICAgICAgICAgIC5nZXRQbGF5ZXJzKClcbiAgICAgICAgICAgICAgICAubWFwKCh0YXJnZXQpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcGFja2V0ID0gbmV3IE1vdmVBY3RvckFic29sdXRlUGFja2V0KCk7XG4gICAgICAgICAgICAgICAgICAgIHBhY2tldC5ydW50aW1lRW50aXR5SWQgPSB0aGlzLnJ1bnRpbWVJZDtcbiAgICAgICAgICAgICAgICAgICAgcGFja2V0LnBvc2l0aW9uID0gdGhpcy5nZXRQb3NpdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGFyZ2V0LmdldE5ldHdvcmtTZXNzaW9uKCkuc2VuZChwYWNrZXQpO1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VuZCBhIG1lc3NhZ2UgdG8gYW4gZW50aXR5LlxuICAgICAqIEByZW1hcmtzIFRoaXMgd2lsbCBzaWxlbnRseSBmYWlsIG9uIG5vbi1jbGllbnQtY29udHJvbGxlZCBlbnRpdGllcy5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZSAtIFRoZSBtZXNzYWdlLlxuICAgICAqIEBwYXJhbSB7VGV4dFR5cGV9IFt0eXBlPVRleHRUeXBlLlJhd10gLSBUaGUgdGV4dCB0eXBlLlxuICAgICAqIEBleGFtcGxlIFNlbmQgXCJIZWxsbyBXb3JsZCFcIiB0byBhIGNsaWVudDpcbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogZW50aXR5LnNlbmRNZXNzYWdlKCdIZWxsbyBXb3JsZCEnKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBwdWJsaWMgc2VuZE1lc3NhZ2UobWVzc2FnZTogc3RyaW5nLCB0eXBlOiBUZXh0VHlwZSA9IFRleHRUeXBlLlJhdyk6IHZvaWQge1xuICAgICAgICB0aGlzLnNlcnZlci5nZXRMb2dnZXIoKS53YXJuKGBFbnRpdHkvc2VuZE1lc3NhZ2UgaXMgbm90IGltcGxlbWVudGVkOiAobWVzc2FnZTogJHttZXNzYWdlfSwgdHlwZTogJHt0eXBlfSlgKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXQgdGhlIGB4YCBwb3NpdGlvbi5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0geCAtIFRoZSBgeGAgY29vcmRpbmF0ZS5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtzdXBwcmVzcz1mYWxzZV0gLSBJZiB0cnVlLCB0aGUgY2xpZW50IHdvbid0IGJlIG5vdGlmaWVkIGFib3V0IHRoZSBwb3NpdGlvbiBjaGFuZ2UuXG4gICAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gdGhlIHggcG9zaXRpb24gaXMgc2V0LlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIGF3YWl0IGVudGl0eS5zZXRYKDEwKTtcbiAgICAgKiBgYGBcbiAgICAgKiBAcmVtYXJrcyBUaGlzIG1ldGhvZCB3aWxsIGFsc28gc2VuZCB0aGUgcG9zaXRpb24gdXBkYXRlIHRvIHRoZSBjbGllbnQgaWYgYHN1cHByZXNzYCBpcyBgZmFsc2VgLlxuICAgICAqL1xuICAgIHB1YmxpYyBhc3luYyBzZXRYKHg6IG51bWJlciwgc3VwcHJlc3MgPSBmYWxzZSk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBzdXBlci5zZXRYLmJpbmQodGhpcykoeCk7XG4gICAgICAgIGlmIChzdXBwcmVzcyAmJiAhdGhpcy5pc1BsYXllcigpKSBhd2FpdCB0aGlzLnNlbmRQb3NpdGlvbigpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldCB0aGUgYHlgIHBvc2l0aW9uLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB5IC0gVGhlIGB5YCBjb29yZGluYXRlLlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW3N1cHByZXNzPWZhbHNlXSAtIElmIHRydWUsIHRoZSBjbGllbnQgd29uJ3QgYmUgbm90aWZpZWQgYWJvdXQgdGhlIHBvc2l0aW9uIGNoYW5nZS5cbiAgICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgeSBwb3NpdGlvbiBpcyBzZXQuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogYXdhaXQgZW50aXR5LnNldFkoMTApO1xuICAgICAqIGBgYFxuICAgICAqIEByZW1hcmtzIFRoaXMgbWV0aG9kIHdpbGwgYWxzbyBzZW5kIHRoZSBwb3NpdGlvbiB1cGRhdGUgdG8gdGhlIGNsaWVudCBpZiBgc3VwcHJlc3NgIGlzIGBmYWxzZWAuXG4gICAgICovXG4gICAgcHVibGljIGFzeW5jIHNldFkoeTogbnVtYmVyLCBzdXBwcmVzcyA9IGZhbHNlKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHN1cGVyLnNldFkuYmluZCh0aGlzKSh5KTtcbiAgICAgICAgaWYgKHN1cHByZXNzICYmICF0aGlzLmlzUGxheWVyKCkpIGF3YWl0IHRoaXMuc2VuZFBvc2l0aW9uKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0IHRoZSBgemAgcG9zaXRpb24uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHogLSBUaGUgYHpgIGNvb3JkaW5hdGUuXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbc3VwcHJlc3M9ZmFsc2VdIC0gSWYgdHJ1ZSwgdGhlIGNsaWVudCB3b24ndCBiZSBub3RpZmllZCBhYm91dCB0aGUgcG9zaXRpb24gY2hhbmdlLlxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSB6IHBvc2l0aW9uIGlzIHNldC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiBhd2FpdCBlbnRpdHkuc2V0WigxMCk7XG4gICAgICogYGBgXG4gICAgICogQHJlbWFya3MgVGhpcyBtZXRob2Qgd2lsbCBhbHNvIHNlbmQgdGhlIHBvc2l0aW9uIHVwZGF0ZSB0byB0aGUgY2xpZW50IGlmIGBzdXBwcmVzc2AgaXMgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBwdWJsaWMgYXN5bmMgc2V0Wih6OiBudW1iZXIsIHN1cHByZXNzID0gZmFsc2UpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgc3VwZXIuc2V0Wi5iaW5kKHRoaXMpKHopO1xuICAgICAgICBpZiAoc3VwcHJlc3MgJiYgIXRoaXMuaXNQbGF5ZXIoKSkgYXdhaXQgdGhpcy5zZW5kUG9zaXRpb24oKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXQgdGhlIGVudGl0eSdzIHBvc2l0aW9uIGFuZCBub3RpZnkgdGhlIGNsaWVudHMuXG4gICAgICogQHBhcmFtIHtvYmplY3R9IG9wdGlvbnMgLSBUaGUgcG9zaXRpb24gb3B0aW9ucy5cbiAgICAgKiBAcGFyYW0ge1ZlY3RvcjN9IG9wdGlvbnMucG9zaXRpb24gLSBUaGUgcG9zaXRpb24uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtvcHRpb25zLnBpdGNoXSAtIFRoZSBwaXRjaC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW29wdGlvbnMueWF3XSAtIFRoZSB5YXcuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtvcHRpb25zLmhlYWRZYXddIC0gVGhlIGhlYWQgeWF3LlxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSBwb3NpdGlvbiBpcyBzZXQuXG4gICAgICovXG4gICAgcHVibGljIGFzeW5jIHNldFBvc2l0aW9uKHtcbiAgICAgICAgcG9zaXRpb24sXG4gICAgICAgIHBpdGNoID0gdGhpcy5waXRjaCxcbiAgICAgICAgeWF3ID0gdGhpcy55YXcsXG4gICAgICAgIGhlYWRZYXcgPSB0aGlzLmhlYWRZYXdcbiAgICB9OiB7XG4gICAgICAgIHBvc2l0aW9uOiBWZWN0b3IzO1xuICAgICAgICBwaXRjaD86IG51bWJlcjtcbiAgICAgICAgeWF3PzogbnVtYmVyO1xuICAgICAgICBoZWFkWWF3PzogbnVtYmVyO1xuICAgIH0pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgdGhpcy5waXRjaCA9IHBpdGNoO1xuICAgICAgICB0aGlzLnlhdyA9IHlhdztcbiAgICAgICAgdGhpcy5oZWFkWWF3ID0gaGVhZFlhdztcblxuICAgICAgICBhd2FpdCBzdXBlci5zZXRYKHBvc2l0aW9uLmdldFgoKSk7XG4gICAgICAgIGF3YWl0IHN1cGVyLnNldFkocG9zaXRpb24uZ2V0WSgpKTtcbiAgICAgICAgYXdhaXQgc3VwZXIuc2V0Wihwb3NpdGlvbi5nZXRaKCkpO1xuXG4gICAgICAgIGF3YWl0IHRoaXMuc2VuZFBvc2l0aW9uKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2sgaWYgdGhlIGVudGl0eSBpcyBhIHBsYXllci5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gYHRydWVgIGlmIHRoZSBlbnRpdHkgaXMgcGxheWVyLWNvbnRyb2xsZWQsIG90aGVyd2lzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIGlmIChlbnRpdHkuaXNQbGF5ZXIoKSkge1xuICAgICAqICAgICBjb25zb2xlLmxvZygnRW50aXR5IGlzIGEgcGxheWVyJyk7XG4gICAgICogfSBlbHNlIHtcbiAgICAgKiAgICAgY29uc29sZS5sb2coJ0VudGl0eSBpcyBub3QgYSBwbGF5ZXInKTtcbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICovXG4gICAgcHVibGljIGlzUGxheWVyKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2sgaWYgdGhlIGVudGl0eSBpcyBhIGNvbnNvbGUgaW5zdGFuY2UuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IGB0cnVlYCBpZiB0aGUgZW50aXR5IGlzIGNvbnNvbGUtY29udHJvbGxlZCwgb3RoZXJ3aXNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogaWYgKGVudGl0eS5pc0NvbnNvbGUoKSkge1xuICAgICAqICAgICBjb25zb2xlLmxvZygnRW50aXR5IGlzIGEgY29uc29sZScpO1xuICAgICAqIH0gZWxzZSB7XG4gICAgICogICAgIGNvbnNvbGUubG9nKCdFbnRpdHkgaXMgbm90IGEgY29uc29sZScpO1xuICAgICAqIH1cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBwdWJsaWMgaXNDb25zb2xlKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRSdW50aW1lSWQoKSA8PSAwbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIGVudGl0eSdzIChwb3RlbnRpYWxseSBjdXN0b20pIG5hbWUuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gVGhlIGVudGl0eSdzIG5hbWUgd2l0aG91dCBmb3JtYXR0aW5nICh1c3VhbGx5IHByZWZpeCAmIHN1ZmZpeCkuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogY29uc3QgbmFtZSA9IGVudGl0eS5nZXROYW1lKCk7XG4gICAgICogY29uc29sZS5sb2coYEVudGl0eSBuYW1lOiAke25hbWV9YCk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgcHVibGljIGdldE5hbWUoKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0Rm9ybWF0dGVkVXNlcm5hbWUoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXQgdGhlIGVudGl0eSdzIG5hbWUuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgLSBUaGUgbmFtZS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiBlbnRpdHkuc2V0TmFtZSgnTXIuIFNoZWVwJyk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgcHVibGljIHNldE5hbWUobmFtZTogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIHRoaXMubWV0YWRhdGEuc2V0TmFtZVRhZyhuYW1lKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIGVudGl0eSdzIGZvcm1hdHRlZCBuYW1lLlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBlbnRpdHkncyBmb3JtYXR0ZWQgbmFtZSAoaW5jbHVkaW5nIHByZWZpeCAmIHN1ZmZpeCkuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogY29uc3QgZm9ybWF0dGVkTmFtZSA9IGVudGl0eS5nZXRGb3JtYXR0ZWRVc2VybmFtZSgpO1xuICAgICAqIGNvbnNvbGUubG9nKGBFbnRpdHkgZm9ybWF0dGVkIG5hbWU6ICR7Zm9ybWF0dGVkTmFtZX1gKTsgLy8gRW50aXR5IGZvcm1hdHRlZCBuYW1lOiBTaGVlcFxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHB1YmxpYyBnZXRGb3JtYXR0ZWRVc2VybmFtZSgpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgdGhpcy5tZXRhZGF0YS5nZXRTdHJpbmcoTWV0YWRhdGFGbGFnLk5BTUVUQUcpIHx8XG4gICAgICAgICAgICAvLyBSZXBsYWNlIGFsbCAnXycgd2l0aCBhICcgJyBhbmQgY2FwaXRhbGl6ZSBlYWNoIHdvcmQgYWZ0ZXJ3YXJkcyxcbiAgICAgICAgICAgIC8vIHNob3VsZCBwcm9iYWJseSBiZSByZXBsYWNlZCB3aXRoIHJlZ2V4LlxuICAgICAgICAgICAgKCgodGhpcy5jb25zdHJ1Y3RvciBhcyBhbnkpPy5NT0JfSUQgYXMgc3RyaW5nKSB8fCAnVW5rbm93biBFbnRpdHknKVxuICAgICAgICAgICAgICAgIC5zcGxpdCgnOicpWzFdIVxuICAgICAgICAgICAgICAgIC5yZXBsYWNlQWxsKCdfJywgJyAnKVxuICAgICAgICAgICAgICAgIC5zcGxpdCgnICcpXG4gICAgICAgICAgICAgICAgLm1hcCgod29yZCkgPT4gd29yZFswXSEudG9VcHBlckNhc2UoKSArIHdvcmQuc2xpY2UoMSwgd29yZC5sZW5ndGgpKVxuICAgICAgICAgICAgICAgIC5qb2luKCcgJylcbiAgICAgICAgKTtcbiAgICB9XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQWtCQSxJQUFhLGFBQWIsY0FBZ0MsdUJBQUEsU0FBUztDQUNyQztDQUNBO0NBQ0E7Q0FFQTtDQUNBO0NBQ0E7Ozs7Ozs7Ozs7Ozs7Q0FjQSxZQUFtQixFQUNmLE1BQ0EsV0FDQSxRQUFRLEdBQ1IsTUFBTSxHQUNOLFVBQVUsR0FDVixHQUFHLFdBU0o7RUFDQyxNQUFNLEdBQUcsR0FBRyxHQUFHLFFBQVEsS0FBSztFQUU1QixLQUFLLE9BQU8sUUFBUSxtQkFBQSxRQUFLLGFBQWE7RUFDdEMsS0FBSyxZQUFZO0VBQ2pCLEtB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