UNPKG

@jsprismarine/prismarine

Version:

Dedicated Minecraft Bedrock Edition server written in TypeScript

411 lines (406 loc) 44.2 kB
'use strict'; Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); const math = require('@jsprismarine/math'); const network_packet_AddActorPacket = require('../network/packet/AddActorPacket.cjs.cjs'); const network_packet_MoveActorAbsolutePacket = require('../network/packet/MoveActorAbsolutePacket.cjs.cjs'); const network_packet_RemoveActorPacket = require('../network/packet/RemoveActorPacket.cjs.cjs'); const network_type_TextType = require('../network/type/TextType.cjs.cjs'); const utils_UUID = require('../utils/UUID.cjs.cjs'); const world_Position = require('../world/Position.cjs.cjs'); const entity_Attribute = require('./Attribute.cjs.cjs'); const entity_Metadata = require('./Metadata.cjs.cjs'); class EntityLike extends 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 ?? 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 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 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 math.Vector3(e.getX(), e.getY(), e.getZ()))); const closest2 = Math.min(...distances); return points.find((_e, i) => distances[i] - closest2 < eps); }; return [ closest( position, entities.filter((entity) => entity.getRuntimeId() !== this.runtimeId) ) ]; } } 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 entity_Metadata.Metadata(); /** * Entity attributes. */ attributes = new 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 network_packet_AddActorPacket.default(); packet.runtimeEntityId = this.getRuntimeId(); packet.type = this.constructor.MOB_ID; packet.position = this.getPosition(); packet.motion = new 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 network_packet_RemoveActorPacket.default(); packet.uniqueEntityId = this.runtimeId; await Promise.all(players.map(async (player2) => player2.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 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 = 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(entity_Metadata.MetadataFlag.NAMETAG) || // Replace all '_' with a ' ' and capitalize each word afterwards, // should probably be replaced with regex. (this.constructor?.MOB_ID || "Unknown Entity").split(":")[1].replaceAll("_", " ").split(" ").map((word) => word[0].toUpperCase() + word.slice(1, word.length)).join(" "); } } exports.Entity = Entity; exports.EntityLike = EntityLike; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRW50aXR5LmNqcy5janMiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9lbnRpdHkvRW50aXR5LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFZlY3RvcjMgfSBmcm9tICdAanNwcmlzbWFyaW5lL21hdGgnO1xuaW1wb3J0IHR5cGUgUGxheWVyIGZyb20gJy4uL1BsYXllcic7XG5pbXBvcnQgdHlwZSBTZXJ2ZXIgZnJvbSAnLi4vU2VydmVyJztcbmltcG9ydCBBZGRBY3RvclBhY2tldCBmcm9tICcuLi9uZXR3b3JrL3BhY2tldC9BZGRBY3RvclBhY2tldCc7XG5pbXBvcnQgTW92ZUFjdG9yQWJzb2x1dGVQYWNrZXQgZnJvbSAnLi4vbmV0d29yay9wYWNrZXQvTW92ZUFjdG9yQWJzb2x1dGVQYWNrZXQnO1xuaW1wb3J0IFJlbW92ZUFjdG9yUGFja2V0IGZyb20gJy4uL25ldHdvcmsvcGFja2V0L1JlbW92ZUFjdG9yUGFja2V0JztcbmltcG9ydCBUZXh0VHlwZSBmcm9tICcuLi9uZXR3b3JrL3R5cGUvVGV4dFR5cGUnO1xuaW1wb3J0IFVVSUQgZnJvbSAnLi4vdXRpbHMvVVVJRCc7XG5pbXBvcnQgeyBQb3NpdGlvbiB9IGZyb20gJy4uL3dvcmxkL1Bvc2l0aW9uJztcbmltcG9ydCB0eXBlIHsgV29ybGQgfSBmcm9tICcuLi93b3JsZC9Xb3JsZCc7XG5pbXBvcnQgeyBBdHRyaWJ1dGVzIH0gZnJvbSAnLi9BdHRyaWJ1dGUnO1xuaW1wb3J0IHsgTWV0YWRhdGEsIE1ldGFkYXRhRmxhZyB9IGZyb20gJy4vTWV0YWRhdGEnO1xuXG4vKipcbiAqIEVudGl0eS1saWtlIGNsYXNzLlxuICogQGNsYXNzXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGNsYXNzIEVudGl0eUxpa2UgZXh0ZW5kcyBQb3NpdGlvbiB7XG4gICAgcHJvdGVjdGVkIHJlYWRvbmx5IHV1aWQ6IHN0cmluZztcbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgcnVudGltZUlkOiBiaWdpbnQ7XG4gICAgcHJvdGVjdGVkIHJlYWRvbmx5IHNlcnZlcjogU2VydmVyO1xuXG4gICAgcHVibGljIHBpdGNoOiBudW1iZXI7XG4gICAgcHVibGljIHlhdzogbnVtYmVyO1xuICAgIHB1YmxpYyBoZWFkWWF3OiBudW1iZXI7XG5cbiAgICAvKipcbiAgICAgKiBFbnRpdHlMaWtlIGNvbnN0cnVjdG9yLlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBvcHRpb25zIC0gVGhlIGVudGl0eS1saWtlIG9wdGlvbnMuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdGlvbnMudXVpZCAtIFRoZSBlbnRpdHkncyBydW50aW1lIGlkLlxuICAgICAqIEBwYXJhbSB7YmlnaW50fSBvcHRpb25zLnJ1bnRpbWVJZCAtIFRoZSBlbnRpdHkncyBydW50aW1lIGlkLlxuICAgICAqIEBwYXJhbSB7U2VydmVyfSBvcHRpb25zLnNlcnZlciAtIFRoZSBzZXJ2ZXIgaW5zdGFuY2UuXG4gICAgICogQHBhcmFtIHtXb3JsZH0gW29wdGlvbnMud29ybGRdIC0gVGhlIHdvcmxkIHRoZSBlbnRpdHkgYmVsb25ncyB0by5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW29wdGlvbnMucGl0Y2g9MF0gLSBUaGUgcGl0Y2guXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtvcHRpb25zLnlhdz0wXSAtIFRoZSB5YXcuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtvcHRpb25zLmhlYWRZYXc9MF0gLSBUaGUgaGVhZCB5YXcuXG4gICAgICogQHJldHVybnMge0VudGl0eUxpa2V9IFRoZSBlbnRpdHktbGlrZSBpbnN0YW5jZS5cbiAgICAgKi9cbiAgICBwdWJsaWMgY29uc3RydWN0b3Ioe1xuICAgICAgICB1dWlkLFxuICAgICAgICBydW50aW1lSWQsXG4gICAgICAgIHBpdGNoID0gMCxcbiAgICAgICAgeWF3ID0gMCxcbiAgICAgICAgaGVhZFlhdyA9IDAsXG4gICAgICAgIC4uLm9wdGlvbnNcbiAgICB9OiB7XG4gICAgICAgIHV1aWQ/OiBzdHJpbmc7XG4gICAgICAgIHJ1bnRpbWVJZDogYmlnaW50O1xuICAgICAgICBwaXRjaD86IG51bWJlcjtcbiAgICAgICAgeWF3PzogbnVtYmVyO1xuICAgICAgICBoZWFkWWF3PzogbnVtYmVyO1xuICAgICAgICBzZXJ2ZXI6IFNlcnZlcjtcbiAgICAgICAgd29ybGQ6IFdvcmxkO1xuICAgIH0pIHtcbiAgICAgICAgc3VwZXIoMCwgMCwgMCwgb3B0aW9ucy53b3JsZCk7IC8vIFRPRE9cblxuICAgICAgICB0aGlzLnV1aWQgPSB1dWlkID8/IFVVSUQucmFuZG9tU3RyaW5nKCk7XG4gICAgICAgIHRoaXMucnVudGltZUlkID0gcnVudGltZUlkO1xuICAgICAgICB0aGlzLnNlcnZlciA9IG9wdGlvbnMuc2VydmVyO1xuXG4gICAgICAgIHRoaXMucGl0Y2ggPSBwaXRjaDtcbiAgICAgICAgdGhpcy55YXcgPSB5YXc7XG4gICAgICAgIHRoaXMuaGVhZFlhdyA9IGhlYWRZYXc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IHRoZSBlbnRpdHkncyBydW50aW1lIGlkLlxuICAgICAqIEByZXR1cm5zIHtiaWdpbnR9IFRoZSBlbnRpdHkncyBydW50aW1lIGlkLlxuICAgICAqL1xuICAgIHB1YmxpYyBnZXRSdW50aW1lSWQoKTogYmlnaW50IHtcbiAgICAgICAgcmV0dXJuIHRoaXMucnVudGltZUlkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgc2VydmVyIGluc3RhbmNlLlxuICAgICAqIEByZXR1cm5zIHtTZXJ2ZXJ9IFRoZSBzZXJ2ZXIgaW5zdGFuY2UuXG4gICAgICovXG4gICAgcHVibGljIGdldFNlcnZlcigpOiBTZXJ2ZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5zZXJ2ZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IHRoZSBlbnRpdHkncyBwb3NpdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7VmVjdG9yM30gVGhlIGVudGl0eSdzIHBvc2l0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIGNvbnN0IHBvc2l0aW9uID0gZW50aXR5LmdldFBvc2l0aW9uKCk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgcHVibGljIGdldFBvc2l0aW9uKCk6IFZlY3RvcjMge1xuICAgICAgICByZXR1cm4gbmV3IFZlY3RvcjModGhpcy5nZXRYKCksIHRoaXMuZ2V0WSgpLCB0aGlzLmdldFooKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgbmVhcmVzdCBlbnRpdHkgZnJvbSB0aGUgY3VycmVudCBlbnRpdHkuXG4gICAgICogQHRvZG8gQ3VzdG9taXphYmxlIHJhZGl1c1xuICAgICAqIEBwYXJhbSB7RW50aXR5W119IFtlbnRpdGllcz10aGlzLmdldFdvcmxkKCkuZ2V0RW50aXRpZXMoKV0gLSBUaGUgZW50aXRpZXMgdG8gY29tcGFyZSB0aGUgZGlzdGFuY2UgYmV0d2Vlbi5cbiAgICAgKiBAcmV0dXJucyB7RW50aXR5W119IFRoZSBuZWFyZXN0IGVudGl0eS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiBjb25zdCBuZWFyZXN0RW50aXR5ID0gZW50aXR5LmdldE5lYXJlc3RFbnRpdHkoKTtcbiAgICAgKiBjb25zb2xlLmxvZygnTmVhcmVzdCBlbnRpdHk6JywgbmVhcmVzdEVudGl0eSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgcHVibGljIGdldE5lYXJlc3RFbnRpdHkoZW50aXRpZXM6IEVudGl0eVtdID0gdGhpcy5nZXRXb3JsZCgpLmdldEVudGl0aWVzKCkpOiBFbnRpdHlbXSB7XG4gICAgICAgIGNvbnN0IHBvc2l0aW9uID0gbmV3IFZlY3RvcjModGhpcy5nZXRYKCksIHRoaXMuZ2V0WSgpLCB0aGlzLmdldFooKSk7XG4gICAgICAgIGNvbnN0IGRpc3RhbmNlID0gKGE6IFZlY3RvcjMsIGI6IFZlY3RvcjMpID0+XG4gICAgICAgICAgICBNYXRoLmh5cG90KGIuZ2V0WCgpIC0gYS5nZXRYKCksIGIuZ2V0WSgpIC0gYS5nZXRZKCksIGIuZ2V0WigpIC0gYS5nZXRaKCkpO1xuXG4gICAgICAgIGNvbnN0IGNsb3Nlc3QgPSAodGFyZ2V0OiBWZWN0b3IzLCBwb2ludHM6IEVudGl0eVtdLCBlcHMgPSAwLjAwMDAxKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBkaXN0YW5jZXMgPSBwb2ludHMubWFwKChlKSA9PiBkaXN0YW5jZSh0YXJnZXQsIG5ldyBWZWN0b3IzKGUuZ2V0WCgpLCBlLmdldFkoKSwgZS5nZXRaKCkpKSk7XG4gICAgICAgICAgICBjb25zdCBjbG9zZXN0ID0gTWF0aC5taW4oLi4uZGlzdGFuY2VzKTtcbiAgICAgICAgICAgIHJldHVybiBwb2ludHMuZmluZCgoX2UsIGkpID0+IGRpc3RhbmNlc1tpXSEgLSBjbG9zZXN0IDwgZXBzKSE7XG4gICAgICAgIH07XG5cbiAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgIGNsb3Nlc3QoXG4gICAgICAgICAgICAgICAgcG9zaXRpb24sXG4gICAgICAgICAgICAgICAgZW50aXRpZXMuZmlsdGVyKChlbnRpdHkpID0+IGVudGl0eS5nZXRSdW50aW1lSWQoKSAhPT0gdGhpcy5ydW50aW1lSWQpXG4gICAgICAgICAgICApXG4gICAgICAgIF07XG4gICAgfVxufVxuXG4vKipcbiAqIFRoZSBiYXNlIGNsYXNzIGZvciBhbGwgZW50aXRpZXMgaW5jbHVkaW5nIGBQbGF5ZXJgLlxuICogQGNsYXNzXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBjbGFzcyBFbnRpdHkgZXh0ZW5kcyBFbnRpdHlMaWtlIHtcbiAgICAvKipcbiAgICAgKiBUaGUgZ2xvYmFsIHJ1bnRpbWUgaWQgY291bnRlci5cbiAgICAgKiBAaW50ZXJuYWxcbiAgICAgKi9cbiAgICBwdWJsaWMgc3RhdGljIHJ1bnRpbWVJZENvdW50ID0gMG47XG5cbiAgICAvKipcbiAgICAgKiBUaGUgZW50aXR5J3MgbmFtZXNwYWNlIElELlxuICAgICAqL1xuICAgIHByb3RlY3RlZCBzdGF0aWMgTU9CX0lEOiBzdHJpbmcgPSAnanNwcmlzbWFyaW5lOnVua25vd25fZW50aXR5JztcblxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgZW50aXR5IHR5cGUuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gVGhlIGVudGl0eSdzIG5hbWVzcGFjZSBJRC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiBjb25zdCBlbnRpdHlUeXBlID0gZW50aXR5LmdldFR5cGUoKTtcbiAgICAgKiBjb25zb2xlLmxvZyhgRW50aXR5IHR5cGU6ICR7ZW50aXR5VHlwZX1gKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0VHlwZSgpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gKHRoaXMuY29uc3RydWN0b3IgYXMgYW55KS5NT0JfSUQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRW50aXR5IG1ldGFkYXRhLlxuICAgICAqL1xuICAgIHB1YmxpYyByZWFkb25seSBtZXRhZGF0YSA9IG5ldyBNZXRhZGF0YSgpO1xuXG4gICAgLyoqXG4gICAgICogRW50aXR5IGF0dHJpYnV0ZXMuXG4gICAgICovXG4gICAgcHVibGljIHJlYWRvbmx5IGF0dHJpYnV0ZXMgPSBuZXcgQXR0cmlidXRlcygpO1xuXG4gICAgLyoqXG4gICAgICogRW50aXR5IGNvbnN0cnVjdG9yLlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBvcHRpb25zIC0gVGhlIGVudGl0eSBvcHRpb25zLlxuICAgICAqIEBwYXJhbSB7V29ybGR9IG9wdGlvbnMud29ybGQgLSBUaGUgd29ybGQgdGhlIGVudGl0eSBiZWxvbmdzIHRvLlxuICAgICAqIEBwYXJhbSB7U2VydmVyfSBvcHRpb25zLnNlcnZlciAtIFRoZSBzZXJ2ZXIgaW5zdGFuY2UuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtvcHRpb25zLnV1aWRdIC0gVGhlIGVudGl0eSdzIFVVSUQuXG4gICAgICogQHJldHVybnMge0VudGl0eX0gVGhlIGVudGl0eSBpbnN0YW5jZS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiBjb25zdCBlbnRpdHkgPSBuZXcgRW50aXR5KHtcbiAgICAgKiAgICAgd29ybGQ6IHNlcnZlci5nZXRXb3JsZE1hbmFnZXIoKS5nZXREZWZhdWx0V29ybGQoKSxcbiAgICAgKiAgICAgc2VydmVyXG4gICAgICogfSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgcHVibGljIGNvbnN0cnVjdG9yKHsgd29ybGQsIC4uLm9wdGlvbnMgfTogT21pdDxDb25zdHJ1Y3RvclBhcmFtZXRlcnM8dHlwZW9mIEVudGl0eUxpa2U+WzBdLCAncnVudGltZUlkJz4pIHtcbiAgICAgICAgRW50aXR5LnJ1bnRpbWVJZENvdW50ICs9IDFuO1xuICAgICAgICBzdXBlcih7XG4gICAgICAgICAgICB3b3JsZCxcbiAgICAgICAgICAgIC4uLm9wdGlvbnMsXG4gICAgICAgICAgICBydW50aW1lSWQ6IEVudGl0eS5ydW50aW1lSWRDb3VudFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVubmVjZXNzYXJ5LWNvbmRpdGlvblxuICAgICAgICBpZiAod29ybGQpIHN1cGVyLnNldFdvcmxkKHdvcmxkKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0IFtTeW1ib2wudG9TdHJpbmdUYWddKCk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiBgRW50aXR5KCR7dGhpcy50b1N0cmluZygpfSlgO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbnZlcnQgdG8gYSBzdHJpbmcgcmVwcmVzZW50YXRpb24uXG4gICAgICogQHJldHVybnMge3N0cmluZ30gVGhlIHN0cmluZy5cbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogY29uc29sZS5sb2coZW50aXR5LnRvU3RyaW5nKCkpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHB1YmxpYyB0b1N0cmluZygpIHtcbiAgICAgICAgcmV0dXJuIGB1dWlkOiDCp2Eke3RoaXMuZ2V0VVVJRCgpfcKnciwgaWQ6IMKnYSR7dGhpcy5nZXRSdW50aW1lSWQoKX3Cp3IsIG5hbWU6IMKnYiR7dGhpcy5nZXROYW1lKCl9wqdyLCB0eXBlOiDCp2Ike3RoaXMuZ2V0VHlwZSgpfcKnciwgJHtzdXBlci50b1N0cmluZygpfWA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IHRoZSBlbnRpdHkncyBydW50aW1lIGlkLlxuICAgICAqIEByZXR1cm5zIHtiaWdpbnR9IFRoZSBlbnRpdHkncyBydW50aW1lIGlkLlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIGNvbnN0IGVudGl0eUlkID0gZW50aXR5LmdldFJ1bnRpbWVJZCgpO1xuICAgICAqIGNvbnNvbGUubG9nKGVudGl0eUlkKTsgLy8gRXguIE91dHB1dDogMW5cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0UnVudGltZUlkKCk6IGJpZ2ludCB7XG4gICAgICAgIHJldHVybiB0aGlzLnJ1bnRpbWVJZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIGVudGl0eSdzIFVVSUQuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gVGhlIGVudGl0eSdzIFVVSUQuXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIGNvbnNvbGUubG9nKGVudGl0eS5nZXRVVUlEKCkpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHB1YmxpYyBnZXRVVUlEKCk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiB0aGlzLnV1aWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRmlyZWQgZXZlcnkgdGljayBmcm9tIHRoZSBldmVudCBzdWJzY3JpcHRpb24gaW4gdGhlIGNvbnN0cnVjdG9yLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBfdGljayAtIFRoZSBjdXJyZW50IHdvcmxkLXRpY2suXG4gICAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gdGhlIHVwZGF0ZSBpcyBjb21wbGV0ZS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiBlbnRpdHkudXBkYXRlKDEwKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBwdWJsaWMgYXN5bmMgdXBkYXRlKF90aWNrOiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+IHt9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIHNlcnZlciBpbnN0YW5jZS5cbiAgICAgKiBAcmV0dXJucyB7U2VydmVyfSBUaGUgc2VydmVyIGluc3RhbmNlLlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIGNvbnN0IHNlcnZlciA9IGVudGl0eS5nZXRTZXJ2ZXIoKTtcbiAgICAgKiAvLyBEbyB0aGluZ3Mgd2l0aCB0aGUgc2VydmVyLlxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHB1YmxpYyBnZXRTZXJ2ZXIoKTogU2VydmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2VydmVyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNwYXduIHRoZSBlbnRpdHkuXG4gICAgICogQHRvZG8gYG1vdGlvbmAsIGBwaXRjaGAgJiBgeWF3YCBpcyB1bmltcGxlbWVudGVkLlxuICAgICAqIEBwYXJhbSB7UGxheWVyfSBbcGxheWVyXSAtIFRoZSBwbGF5ZXIgdG8gc2VuZCB0aGUgcGFja2V0IHRvLlxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSBlbnRpdHkgaXMgc3Bhd25lZC5cbiAgICAgKi9cbiAgICBwdWJsaWMgYXN5bmMgc2VuZFNwYXduKHBsYXllcj86IFBsYXllcik6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBjb25zdCBwbGF5ZXJzOiBQbGF5ZXJbXSA9IHBsYXllciA/IFtwbGF5ZXJdIDogdGhpcy5nZXRXb3JsZCgpLmdldFBsYXllcnMoKTtcblxuICAgICAgICBjb25zdCBwYWNrZXQgPSBuZXcgQWRkQWN0b3JQYWNrZXQoKTtcbiAgICAgICAgcGFja2V0LnJ1bnRpbWVFbnRpdHlJZCA9IHRoaXMuZ2V0UnVudGltZUlkKCk7XG4gICAgICAgIHBhY2tldC50eXBlID0gKHRoaXMuY29uc3RydWN0b3IgYXMgYW55KS5NT0JfSUQ7IC8vIFRPRE9cbiAgICAgICAgcGFja2V0LnBvc2l0aW9uID0gdGhpcy5nZXRQb3NpdGlvbigpO1xuICAgICAgICBwYWNrZXQubW90aW9uID0gbmV3IFZlY3RvcjMoMCwgMCwgMCk7IC8vIFRPRE86IG1vdGlvblxuICAgICAgICBwYWNrZXQucGl0Y2ggPSB0aGlzLnBpdGNoO1xuICAgICAgICBwYWNrZXQueWF3ID0gdGhpcy55YXc7XG4gICAgICAgIHBhY2tldC5oZWFkWWF3ID0gdGhpcy5oZWFkWWF3O1xuICAgICAgICBwYWNrZXQubWV0YWRhdGEgPSB0aGlzLm1ldGFkYXRhO1xuICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChwbGF5ZXJzLm1hcChhc3luYyAocCkgPT4gcC5nZXROZXR3b3JrU2Vzc2lvbigpLnNlbmQocGFja2V0KSkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIERlc3Bhd24gdGhlIGVudGl0eS5cbiAgICAgKiBAcGFyYW0ge1BsYXllcn0gW3BsYXllcl0gLSBUaGUgcGxheWVyIHRvIHNlbmQgdGhlIHBhY2tldCB0bywgaWYgbm90IHNwZWNpZmllZCwgYWxsIHBsYXllcnMgaW4gdGhlIHdvcmxkIHdpbGwgcmVjZWl2ZSB0aGUgcGFja2V0LlxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSBlbnRpdHkgaXMgZGVzcGF3bmVkLlxuICAgICAqL1xuICAgIHB1YmxpYyBhc3luYyBzZW5kRGVzcGF3bihwbGF5ZXI/OiBQbGF5ZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgY29uc3QgcGxheWVyczogUGxheWVyW10gPSBwbGF5ZXIgPyBbcGxheWVyXSA6IHRoaXMuZ2V0V29ybGQoKS5nZXRQbGF5ZXJzKCk7XG5cbiAgICAgICAgY29uc3QgcGFja2V0ID0gbmV3IFJlbW92ZUFjdG9yUGFja2V0KCk7XG4gICAgICAgIHBhY2tldC51bmlxdWVFbnRpdHlJZCA9IHRoaXMucnVudGltZUlkO1xuICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChwbGF5ZXJzLm1hcChhc3luYyAocGxheWVyKSA9PiBwbGF5ZXIuZ2V0TmV0d29ya1Nlc3Npb24oKS5zZW5kKHBhY2tldCkpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZW5kIHRoZSBwb3NpdGlvbiB0byBhbGwgdGhlIHBsYXllcnMgaW4gdGhlIHNhbWUgd29ybGQuXG4gICAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gdGhlIHBvc2l0aW9uIGlzIHNlbnQuXG4gICAgICovXG4gICAgcHVibGljIGFzeW5jIHNlbmRQb3NpdGlvbigpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgICAgICB0aGlzLmdldFdvcmxkKClcbiAgICAgICAgICAgICAgICAuZ2V0UGxheWVycygpXG4gICAgICAgICAgICAgICAgLm1hcCgodGFyZ2V0KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHBhY2tldCA9IG5ldyBNb3ZlQWN0b3JBYnNvbHV0ZVBhY2tldCgpO1xuICAgICAgICAgICAgICAgICAgICBwYWNrZXQucnVudGltZUVudGl0eUlkID0gdGhpcy5ydW50aW1lSWQ7XG4gICAgICAgICAgICAgICAgICAgIHBhY2tldC5wb3NpdGlvbiA9IHRoaXMuZ2V0UG9zaXRpb24oKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRhcmdldC5nZXROZXR3b3JrU2Vzc2lvbigpLnNlbmQocGFja2V0KTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNlbmQgYSBtZXNzYWdlIHRvIGFuIGVudGl0eS5cbiAgICAgKiBAcmVtYXJrcyBUaGlzIHdpbGwgc2lsZW50bHkgZmFpbCBvbiBub24tY2xpZW50LWNvbnRyb2xsZWQgZW50aXRpZXMuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2UgLSBUaGUgbWVzc2FnZS5cbiAgICAgKiBAcGFyYW0ge1RleHRUeXBlfSBbdHlwZT1UZXh0VHlwZS5SYXddIC0gVGhlIHRleHQgdHlwZS5cbiAgICAgKiBAZXhhbXBsZSBTZW5kIFwiSGVsbG8gV29ybGQhXCIgdG8gYSBjbGllbnQ6XG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIGVudGl0eS5zZW5kTWVzc2FnZSgnSGVsbG8gV29ybGQhJyk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgcHVibGljIHNlbmRNZXNzYWdlKG1lc3NhZ2U6IHN0cmluZywgdHlwZTogVGV4dFR5cGUgPSBUZXh0VHlwZS5SYXcpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zZXJ2ZXIuZ2V0TG9nZ2VyKCkud2FybihgRW50aXR5L3NlbmRNZXNzYWdlIGlzIG5vdCBpbXBsZW1lbnRlZDogKG1lc3NhZ2U6ICR7bWVzc2FnZX0sIHR5cGU6ICR7dHlwZX0pYCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0IHRoZSBgeGAgcG9zaXRpb24uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHggLSBUaGUgYHhgIGNvb3JkaW5hdGUuXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbc3VwcHJlc3M9ZmFsc2VdIC0gSWYgdHJ1ZSwgdGhlIGNsaWVudCB3b24ndCBiZSBub3RpZmllZCBhYm91dCB0aGUgcG9zaXRpb24gY2hhbmdlLlxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSB4IHBvc2l0aW9uIGlzIHNldC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiBhd2FpdCBlbnRpdHkuc2V0WCgxMCk7XG4gICAgICogYGBgXG4gICAgICogQHJlbWFya3MgVGhpcyBtZXRob2Qgd2lsbCBhbHNvIHNlbmQgdGhlIHBvc2l0aW9uIHVwZGF0ZSB0byB0aGUgY2xpZW50IGlmIGBzdXBwcmVzc2AgaXMgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBwdWJsaWMgYXN5bmMgc2V0WCh4OiBudW1iZXIsIHN1cHByZXNzID0gZmFsc2UpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgc3VwZXIuc2V0WC5iaW5kKHRoaXMpKHgpO1xuICAgICAgICBpZiAoc3VwcHJlc3MgJiYgIXRoaXMuaXNQbGF5ZXIoKSkgYXdhaXQgdGhpcy5zZW5kUG9zaXRpb24oKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXQgdGhlIGB5YCBwb3NpdGlvbi5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0geSAtIFRoZSBgeWAgY29vcmRpbmF0ZS5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtzdXBwcmVzcz1mYWxzZV0gLSBJZiB0cnVlLCB0aGUgY2xpZW50IHdvbid0IGJlIG5vdGlmaWVkIGFib3V0IHRoZSBwb3NpdGlvbiBjaGFuZ2UuXG4gICAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gdGhlIHkgcG9zaXRpb24gaXMgc2V0LlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIGF3YWl0IGVudGl0eS5zZXRZKDEwKTtcbiAgICAgKiBgYGBcbiAgICAgKiBAcmVtYXJrcyBUaGlzIG1ldGhvZCB3aWxsIGFsc28gc2VuZCB0aGUgcG9zaXRpb24gdXBkYXRlIHRvIHRoZSBjbGllbnQgaWYgYHN1cHByZXNzYCBpcyBgZmFsc2VgLlxuICAgICAqL1xuICAgIHB1YmxpYyBhc3luYyBzZXRZKHk6IG51bWJlciwgc3VwcHJlc3MgPSBmYWxzZSk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBzdXBlci5zZXRZLmJpbmQodGhpcykoeSk7XG4gICAgICAgIGlmIChzdXBwcmVzcyAmJiAhdGhpcy5pc1BsYXllcigpKSBhd2FpdCB0aGlzLnNlbmRQb3NpdGlvbigpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldCB0aGUgYHpgIHBvc2l0aW9uLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB6IC0gVGhlIGB6YCBjb29yZGluYXRlLlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW3N1cHByZXNzPWZhbHNlXSAtIElmIHRydWUsIHRoZSBjbGllbnQgd29uJ3QgYmUgbm90aWZpZWQgYWJvdXQgdGhlIHBvc2l0aW9uIGNoYW5nZS5cbiAgICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgeiBwb3NpdGlvbiBpcyBzZXQuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogYXdhaXQgZW50aXR5LnNldFooMTApO1xuICAgICAqIGBgYFxuICAgICAqIEByZW1hcmtzIFRoaXMgbWV0aG9kIHdpbGwgYWxzbyBzZW5kIHRoZSBwb3NpdGlvbiB1cGRhdGUgdG8gdGhlIGNsaWVudCBpZiBgc3VwcHJlc3NgIGlzIGBmYWxzZWAuXG4gICAgICovXG4gICAgcHVibGljIGFzeW5jIHNldFooejogbnVtYmVyLCBzdXBwcmVzcyA9IGZhbHNlKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHN1cGVyLnNldFouYmluZCh0aGlzKSh6KTtcbiAgICAgICAgaWYgKHN1cHByZXNzICYmICF0aGlzLmlzUGxheWVyKCkpIGF3YWl0IHRoaXMuc2VuZFBvc2l0aW9uKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0IHRoZSBlbnRpdHkncyBwb3NpdGlvbiBhbmQgbm90aWZ5IHRoZSBjbGllbnRzLlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBvcHRpb25zIC0gVGhlIHBvc2l0aW9uIG9wdGlvbnMuXG4gICAgICogQHBhcmFtIHtWZWN0b3IzfSBvcHRpb25zLnBvc2l0aW9uIC0gVGhlIHBvc2l0aW9uLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbb3B0aW9ucy5waXRjaF0gLSBUaGUgcGl0Y2guXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtvcHRpb25zLnlhd10gLSBUaGUgeWF3LlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbb3B0aW9ucy5oZWFkWWF3XSAtIFRoZSBoZWFkIHlhdy5cbiAgICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgcG9zaXRpb24gaXMgc2V0LlxuICAgICAqL1xuICAgIHB1YmxpYyBhc3luYyBzZXRQb3NpdGlvbih7XG4gICAgICAgIHBvc2l0aW9uLFxuICAgICAgICBwaXRjaCA9IHRoaXMucGl0Y2gsXG4gICAgICAgIHlhdyA9IHRoaXMueWF3LFxuICAgICAgICBoZWFkWWF3ID0gdGhpcy5oZWFkWWF3XG4gICAgfToge1xuICAgICAgICBwb3NpdGlvbjogVmVjdG9yMztcbiAgICAgICAgcGl0Y2g/OiBudW1iZXI7XG4gICAgICAgIHlhdz86IG51bWJlcjtcbiAgICAgICAgaGVhZFlhdz86IG51bWJlcjtcbiAgICB9KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHRoaXMucGl0Y2ggPSBwaXRjaDtcbiAgICAgICAgdGhpcy55YXcgPSB5YXc7XG4gICAgICAgIHRoaXMuaGVhZFlhdyA9IGhlYWRZYXc7XG5cbiAgICAgICAgYXdhaXQgc3VwZXIuc2V0WChwb3NpdGlvbi5nZXRYKCkpO1xuICAgICAgICBhd2FpdCBzdXBlci5zZXRZKHBvc2l0aW9uLmdldFkoKSk7XG4gICAgICAgIGF3YWl0IHN1cGVyLnNldFoocG9zaXRpb24uZ2V0WigpKTtcblxuICAgICAgICBhd2FpdCB0aGlzLnNlbmRQb3NpdGlvbigpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrIGlmIHRoZSBlbnRpdHkgaXMgYSBwbGF5ZXIuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IGB0cnVlYCBpZiB0aGUgZW50aXR5IGlzIHBsYXllci1jb250cm9sbGVkLCBvdGhlcndpc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiBpZiAoZW50aXR5LmlzUGxheWVyKCkpIHtcbiAgICAgKiAgICAgY29uc29sZS5sb2coJ0VudGl0eSBpcyBhIHBsYXllcicpO1xuICAgICAqIH0gZWxzZSB7XG4gICAgICogICAgIGNvbnNvbGUubG9nKCdFbnRpdHkgaXMgbm90IGEgcGxheWVyJyk7XG4gICAgICogfVxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHB1YmxpYyBpc1BsYXllcigpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrIGlmIHRoZSBlbnRpdHkgaXMgYSBjb25zb2xlIGluc3RhbmNlLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBgdHJ1ZWAgaWYgdGhlIGVudGl0eSBpcyBjb25zb2xlLWNvbnRyb2xsZWQsIG90aGVyd2lzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIGlmIChlbnRpdHkuaXNDb25zb2xlKCkpIHtcbiAgICAgKiAgICAgY29uc29sZS5sb2coJ0VudGl0eSBpcyBhIGNvbnNvbGUnKTtcbiAgICAgKiB9IGVsc2Uge1xuICAgICAqICAgICBjb25zb2xlLmxvZygnRW50aXR5IGlzIG5vdCBhIGNvbnNvbGUnKTtcbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICovXG4gICAgcHVibGljIGlzQ29uc29sZSgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0UnVudGltZUlkKCkgPD0gMG47XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IHRoZSBlbnRpdHkncyAocG90ZW50aWFsbHkgY3VzdG9tKSBuYW1lLlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBlbnRpdHkncyBuYW1lIHdpdGhvdXQgZm9ybWF0dGluZyAodXN1YWxseSBwcmVmaXggJiBzdWZmaXgpLlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIGNvbnN0IG5hbWUgPSBlbnRpdHkuZ2V0TmFtZSgpO1xuICAgICAqIGNvbnNvbGUubG9nKGBFbnRpdHkgbmFtZTogJHtuYW1lfWApO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHB1YmxpYyBnZXROYW1lKCk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldEZvcm1hdHRlZFVzZXJuYW1lKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0IHRoZSBlbnRpdHkncyBuYW1lLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIC0gVGhlIG5hbWUuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogZW50aXR5LnNldE5hbWUoJ01yLiBTaGVlcCcpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHB1YmxpYyBzZXROYW1lKG5hbWU6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICB0aGlzLm1ldGFkYXRhLnNldE5hbWVUYWcobmFtZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IHRoZSBlbnRpdHkncyBmb3JtYXR0ZWQgbmFtZS5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgZW50aXR5J3MgZm9ybWF0dGVkIG5hbWUgKGluY2x1ZGluZyBwcmVmaXggJiBzdWZmaXgpLlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIGNvbnN0IGZvcm1hdHRlZE5hbWUgPSBlbnRpdHkuZ2V0Rm9ybWF0dGVkVXNlcm5hbWUoKTtcbiAgICAgKiBjb25zb2xlLmxvZyhgRW50aXR5IGZvcm1hdHRlZCBuYW1lOiAke2Zvcm1hdHRlZE5hbWV9YCk7IC8vIEVudGl0eSBmb3JtYXR0ZWQgbmFtZTogU2hlZXBcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0Rm9ybWF0dGVkVXNlcm5hbWUoKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIHRoaXMubWV0YWRhdGEuZ2V0U3RyaW5nKE1ldGFkYXRhRmxhZy5OQU1FVEFHKSB8fFxuICAgICAgICAgICAgLy8gUmVwbGFjZSBhbGwgJ18nIHdpdGggYSAnICcgYW5kIGNhcGl0YWxpemUgZWFjaCB3b3JkIGFmdGVyd2FyZHMsXG4gICAgICAgICAgICAvLyBzaG91bGQgcHJvYmFibHkgYmUgcmVwbGFjZWQgd2l0aCByZWdleC5cbiAgICAgICAgICAgICgoKHRoaXMuY29uc3RydWN0b3IgYXMgYW55KT8uTU9CX0lEIGFzIHN0cmluZykgfHwgJ1Vua25vd24gRW50aXR5JylcbiAgICAgICAgICAgICAgICAuc3BsaXQoJzonKVsxXSFcbiAgICAgICAgICAgICAgICAucmVwbGFjZUFsbCgnXycsICcgJylcbiAgICAgICAgICAgICAgICAuc3BsaXQoJyAnKVxuICAgICAgICAgICAgICAgIC5tYXAoKHdvcmQpID0+IHdvcmRbMF0hLnRvVXBwZXJDYXNlKCkgKyB3b3JkLnNsaWNlKDEsIHdvcmQubGVuZ3RoKSlcbiAgICAgICAgICAgICAgICAuam9pbignICcpXG4gICAgICAgICk7XG4gICAgfVxufVxuIl0sIm5hbWVzIjpbIlBvc2l0aW9uIiwiVVVJRCIsIlZlY3RvcjMiLCJjbG9zZXN0IiwiTWV0YWRhdGEiLCJBdHRyaWJ1dGVzIiwiQWRkQWN0b3JQYWNrZXQiLCJSZW1vdmVBY3RvclBhY2tldCIsInBsYXllciIsIk1vdmVBY3RvckFic29sdXRlUGFja2V0IiwiVGV4dFR5cGUiLCJNZXRhZGF0YUZsYWciXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7O0FBa0JPLE1BQU0sbUJBQW1CQSx1QkFBUyxDQUFBO0FBQUEsRUFDbEIsSUFBQTtBQUFBLEVBQ0EsU0FBQTtBQUFBLEVBQ0EsTUFBQTtBQUFBLEVB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