@jsprismarine/prismarine
Version:
Dedicated Minecraft Bedrock Edition server written in TypeScript
406 lines (403 loc) • 43.5 kB
JavaScript
import { Vector3 } from '@jsprismarine/math';
import AddActorPacket from '../network/packet/AddActorPacket.es.js';
import MoveActorAbsolutePacket from '../network/packet/MoveActorAbsolutePacket.es.js';
import RemoveActorPacket from '../network/packet/RemoveActorPacket.es.js';
import TextType from '../network/type/TextType.es.js';
import UUID from '../utils/UUID.es.js';
import { Position } from '../world/Position.es.js';
import { Attributes } from './Attribute.es.js';
import { Metadata, MetadataFlag } from './Metadata.es.js';
class EntityLike extends 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 ?? UUID.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 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 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 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 Metadata();
/**
* Entity attributes.
*/
attributes = new 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 AddActorPacket();
packet.runtimeEntityId = this.getRuntimeId();
packet.type = this.constructor.MOB_ID;
packet.position = this.getPosition();
packet.motion = new 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 RemoveActorPacket();
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 MoveActorAbsolutePacket();
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 = TextType.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(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(" ");
}
}
export { Entity, EntityLike };
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRW50aXR5LmVzLmpzIiwic291cmNlcyI6WyIuLi8uLi9zcmMvZW50aXR5L0VudGl0eS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBWZWN0b3IzIH0gZnJvbSAnQGpzcHJpc21hcmluZS9tYXRoJztcbmltcG9ydCB0eXBlIFBsYXllciBmcm9tICcuLi9QbGF5ZXInO1xuaW1wb3J0IHR5cGUgU2VydmVyIGZyb20gJy4uL1NlcnZlcic7XG5pbXBvcnQgQWRkQWN0b3JQYWNrZXQgZnJvbSAnLi4vbmV0d29yay9wYWNrZXQvQWRkQWN0b3JQYWNrZXQnO1xuaW1wb3J0IE1vdmVBY3RvckFic29sdXRlUGFja2V0IGZyb20gJy4uL25ldHdvcmsvcGFja2V0L01vdmVBY3RvckFic29sdXRlUGFja2V0JztcbmltcG9ydCBSZW1vdmVBY3RvclBhY2tldCBmcm9tICcuLi9uZXR3b3JrL3BhY2tldC9SZW1vdmVBY3RvclBhY2tldCc7XG5pbXBvcnQgVGV4dFR5cGUgZnJvbSAnLi4vbmV0d29yay90eXBlL1RleHRUeXBlJztcbmltcG9ydCBVVUlEIGZyb20gJy4uL3V0aWxzL1VVSUQnO1xuaW1wb3J0IHsgUG9zaXRpb24gfSBmcm9tICcuLi93b3JsZC9Qb3NpdGlvbic7XG5pbXBvcnQgdHlwZSB7IFdvcmxkIH0gZnJvbSAnLi4vd29ybGQvV29ybGQnO1xuaW1wb3J0IHsgQXR0cmlidXRlcyB9IGZyb20gJy4vQXR0cmlidXRlJztcbmltcG9ydCB7IE1ldGFkYXRhLCBNZXRhZGF0YUZsYWcgfSBmcm9tICcuL01ldGFkYXRhJztcblxuLyoqXG4gKiBFbnRpdHktbGlrZSBjbGFzcy5cbiAqIEBjbGFzc1xuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBjbGFzcyBFbnRpdHlMaWtlIGV4dGVuZHMgUG9zaXRpb24ge1xuICAgIHByb3RlY3RlZCByZWFkb25seSB1dWlkOiBzdHJpbmc7XG4gICAgcHJvdGVjdGVkIHJlYWRvbmx5IHJ1bnRpbWVJZDogYmlnaW50O1xuICAgIHByb3RlY3RlZCByZWFkb25seSBzZXJ2ZXI6IFNlcnZlcjtcblxuICAgIHB1YmxpYyBwaXRjaDogbnVtYmVyO1xuICAgIHB1YmxpYyB5YXc6IG51bWJlcjtcbiAgICBwdWJsaWMgaGVhZFlhdzogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogRW50aXR5TGlrZSBjb25zdHJ1Y3Rvci5cbiAgICAgKiBAcGFyYW0ge29iamVjdH0gb3B0aW9ucyAtIFRoZSBlbnRpdHktbGlrZSBvcHRpb25zLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRpb25zLnV1aWQgLSBUaGUgZW50aXR5J3MgcnVudGltZSBpZC5cbiAgICAgKiBAcGFyYW0ge2JpZ2ludH0gb3B0aW9ucy5ydW50aW1lSWQgLSBUaGUgZW50aXR5J3MgcnVudGltZSBpZC5cbiAgICAgKiBAcGFyYW0ge1NlcnZlcn0gb3B0aW9ucy5zZXJ2ZXIgLSBUaGUgc2VydmVyIGluc3RhbmNlLlxuICAgICAqIEBwYXJhbSB7V29ybGR9IFtvcHRpb25zLndvcmxkXSAtIFRoZSB3b3JsZCB0aGUgZW50aXR5IGJlbG9uZ3MgdG8uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtvcHRpb25zLnBpdGNoPTBdIC0gVGhlIHBpdGNoLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbb3B0aW9ucy55YXc9MF0gLSBUaGUgeWF3LlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbb3B0aW9ucy5oZWFkWWF3PTBdIC0gVGhlIGhlYWQgeWF3LlxuICAgICAqIEByZXR1cm5zIHtFbnRpdHlMaWtlfSBUaGUgZW50aXR5LWxpa2UgaW5zdGFuY2UuXG4gICAgICovXG4gICAgcHVibGljIGNvbnN0cnVjdG9yKHtcbiAgICAgICAgdXVpZCxcbiAgICAgICAgcnVudGltZUlkLFxuICAgICAgICBwaXRjaCA9IDAsXG4gICAgICAgIHlhdyA9IDAsXG4gICAgICAgIGhlYWRZYXcgPSAwLFxuICAgICAgICAuLi5vcHRpb25zXG4gICAgfToge1xuICAgICAgICB1dWlkPzogc3RyaW5nO1xuICAgICAgICBydW50aW1lSWQ6IGJpZ2ludDtcbiAgICAgICAgcGl0Y2g/OiBudW1iZXI7XG4gICAgICAgIHlhdz86IG51bWJlcjtcbiAgICAgICAgaGVhZFlhdz86IG51bWJlcjtcbiAgICAgICAgc2VydmVyOiBTZXJ2ZXI7XG4gICAgICAgIHdvcmxkOiBXb3JsZDtcbiAgICB9KSB7XG4gICAgICAgIHN1cGVyKDAsIDAsIDAsIG9wdGlvbnMud29ybGQpOyAvLyBUT0RPXG5cbiAgICAgICAgdGhpcy51dWlkID0gdXVpZCA/PyBVVUlELnJhbmRvbVN0cmluZygpO1xuICAgICAgICB0aGlzLnJ1bnRpbWVJZCA9IHJ1bnRpbWVJZDtcbiAgICAgICAgdGhpcy5zZXJ2ZXIgPSBvcHRpb25zLnNlcnZlcjtcblxuICAgICAgICB0aGlzLnBpdGNoID0gcGl0Y2g7XG4gICAgICAgIHRoaXMueWF3ID0geWF3O1xuICAgICAgICB0aGlzLmhlYWRZYXcgPSBoZWFkWWF3O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgZW50aXR5J3MgcnVudGltZSBpZC5cbiAgICAgKiBAcmV0dXJucyB7YmlnaW50fSBUaGUgZW50aXR5J3MgcnVudGltZSBpZC5cbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0UnVudGltZUlkKCk6IGJpZ2ludCB7XG4gICAgICAgIHJldHVybiB0aGlzLnJ1bnRpbWVJZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIHNlcnZlciBpbnN0YW5jZS5cbiAgICAgKiBAcmV0dXJucyB7U2VydmVyfSBUaGUgc2VydmVyIGluc3RhbmNlLlxuICAgICAqL1xuICAgIHB1YmxpYyBnZXRTZXJ2ZXIoKTogU2VydmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2VydmVyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgZW50aXR5J3MgcG9zaXRpb24uXG4gICAgICogQHJldHVybnMge1ZlY3RvcjN9IFRoZSBlbnRpdHkncyBwb3NpdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiBjb25zdCBwb3NpdGlvbiA9IGVudGl0eS5nZXRQb3NpdGlvbigpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHB1YmxpYyBnZXRQb3NpdGlvbigpOiBWZWN0b3IzIHtcbiAgICAgICAgcmV0dXJuIG5ldyBWZWN0b3IzKHRoaXMuZ2V0WCgpLCB0aGlzLmdldFkoKSwgdGhpcy5nZXRaKCkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIG5lYXJlc3QgZW50aXR5IGZyb20gdGhlIGN1cnJlbnQgZW50aXR5LlxuICAgICAqIEB0b2RvIEN1c3RvbWl6YWJsZSByYWRpdXNcbiAgICAgKiBAcGFyYW0ge0VudGl0eVtdfSBbZW50aXRpZXM9dGhpcy5nZXRXb3JsZCgpLmdldEVudGl0aWVzKCldIC0gVGhlIGVudGl0aWVzIHRvIGNvbXBhcmUgdGhlIGRpc3RhbmNlIGJldHdlZW4uXG4gICAgICogQHJldHVybnMge0VudGl0eVtdfSBUaGUgbmVhcmVzdCBlbnRpdHkuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogY29uc3QgbmVhcmVzdEVudGl0eSA9IGVudGl0eS5nZXROZWFyZXN0RW50aXR5KCk7XG4gICAgICogY29uc29sZS5sb2coJ05lYXJlc3QgZW50aXR5OicsIG5lYXJlc3RFbnRpdHkpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHB1YmxpYyBnZXROZWFyZXN0RW50aXR5KGVudGl0aWVzOiBFbnRpdHlbXSA9IHRoaXMuZ2V0V29ybGQoKS5nZXRFbnRpdGllcygpKTogRW50aXR5W10ge1xuICAgICAgICBjb25zdCBwb3NpdGlvbiA9IG5ldyBWZWN0b3IzKHRoaXMuZ2V0WCgpLCB0aGlzLmdldFkoKSwgdGhpcy5nZXRaKCkpO1xuICAgICAgICBjb25zdCBkaXN0YW5jZSA9IChhOiBWZWN0b3IzLCBiOiBWZWN0b3IzKSA9PlxuICAgICAgICAgICAgTWF0aC5oeXBvdChiLmdldFgoKSAtIGEuZ2V0WCgpLCBiLmdldFkoKSAtIGEuZ2V0WSgpLCBiLmdldFooKSAtIGEuZ2V0WigpKTtcblxuICAgICAgICBjb25zdCBjbG9zZXN0ID0gKHRhcmdldDogVmVjdG9yMywgcG9pbnRzOiBFbnRpdHlbXSwgZXBzID0gMC4wMDAwMSkgPT4ge1xuICAgICAgICAgICAgY29uc3QgZGlzdGFuY2VzID0gcG9pbnRzLm1hcCgoZSkgPT4gZGlzdGFuY2UodGFyZ2V0LCBuZXcgVmVjdG9yMyhlLmdldFgoKSwgZS5nZXRZKCksIGUuZ2V0WigpKSkpO1xuICAgICAgICAgICAgY29uc3QgY2xvc2VzdCA9IE1hdGgubWluKC4uLmRpc3RhbmNlcyk7XG4gICAgICAgICAgICByZXR1cm4gcG9pbnRzLmZpbmQoKF9lLCBpKSA9PiBkaXN0YW5jZXNbaV0hIC0gY2xvc2VzdCA8IGVwcykhO1xuICAgICAgICB9O1xuXG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICBjbG9zZXN0KFxuICAgICAgICAgICAgICAgIHBvc2l0aW9uLFxuICAgICAgICAgICAgICAgIGVudGl0aWVzLmZpbHRlcigoZW50aXR5KSA9PiBlbnRpdHkuZ2V0UnVudGltZUlkKCkgIT09IHRoaXMucnVudGltZUlkKVxuICAgICAgICAgICAgKVxuICAgICAgICBdO1xuICAgIH1cbn1cblxuLyoqXG4gKiBUaGUgYmFzZSBjbGFzcyBmb3IgYWxsIGVudGl0aWVzIGluY2x1ZGluZyBgUGxheWVyYC5cbiAqIEBjbGFzc1xuICogQHB1YmxpY1xuICovXG5leHBvcnQgY2xhc3MgRW50aXR5IGV4dGVuZHMgRW50aXR5TGlrZSB7XG4gICAgLyoqXG4gICAgICogVGhlIGdsb2JhbCBydW50aW1lIGlkIGNvdW50ZXIuXG4gICAgICogQGludGVybmFsXG4gICAgICovXG4gICAgcHVibGljIHN0YXRpYyBydW50aW1lSWRDb3VudCA9IDBuO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGVudGl0eSdzIG5hbWVzcGFjZSBJRC5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgc3RhdGljIE1PQl9JRDogc3RyaW5nID0gJ2pzcHJpc21hcmluZTp1bmtub3duX2VudGl0eSc7XG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIGVudGl0eSB0eXBlLlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBlbnRpdHkncyBuYW1lc3BhY2UgSUQuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogY29uc3QgZW50aXR5VHlwZSA9IGVudGl0eS5nZXRUeXBlKCk7XG4gICAgICogY29uc29sZS5sb2coYEVudGl0eSB0eXBlOiAke2VudGl0eVR5cGV9YCk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgcHVibGljIGdldFR5cGUoKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuICh0aGlzLmNvbnN0cnVjdG9yIGFzIGFueSkuTU9CX0lEO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEVudGl0eSBtZXRhZGF0YS5cbiAgICAgKi9cbiAgICBwdWJsaWMgcmVhZG9ubHkgbWV0YWRhdGEgPSBuZXcgTWV0YWRhdGEoKTtcblxuICAgIC8qKlxuICAgICAqIEVudGl0eSBhdHRyaWJ1dGVzLlxuICAgICAqL1xuICAgIHB1YmxpYyByZWFkb25seSBhdHRyaWJ1dGVzID0gbmV3IEF0dHJpYnV0ZXMoKTtcblxuICAgIC8qKlxuICAgICAqIEVudGl0eSBjb25zdHJ1Y3Rvci5cbiAgICAgKiBAcGFyYW0ge29iamVjdH0gb3B0aW9ucyAtIFRoZSBlbnRpdHkgb3B0aW9ucy5cbiAgICAgKiBAcGFyYW0ge1dvcmxkfSBvcHRpb25zLndvcmxkIC0gVGhlIHdvcmxkIHRoZSBlbnRpdHkgYmVsb25ncyB0by5cbiAgICAgKiBAcGFyYW0ge1NlcnZlcn0gb3B0aW9ucy5zZXJ2ZXIgLSBUaGUgc2VydmVyIGluc3RhbmNlLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbb3B0aW9ucy51dWlkXSAtIFRoZSBlbnRpdHkncyBVVUlELlxuICAgICAqIEByZXR1cm5zIHtFbnRpdHl9IFRoZSBlbnRpdHkgaW5zdGFuY2UuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogY29uc3QgZW50aXR5ID0gbmV3IEVudGl0eSh7XG4gICAgICogICAgIHdvcmxkOiBzZXJ2ZXIuZ2V0V29ybGRNYW5hZ2VyKCkuZ2V0RGVmYXVsdFdvcmxkKCksXG4gICAgICogICAgIHNlcnZlclxuICAgICAqIH0pO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHB1YmxpYyBjb25zdHJ1Y3Rvcih7IHdvcmxkLCAuLi5vcHRpb25zIH06IE9taXQ8Q29uc3RydWN0b3JQYXJhbWV0ZXJzPHR5cGVvZiBFbnRpdHlMaWtlPlswXSwgJ3J1bnRpbWVJZCc+KSB7XG4gICAgICAgIEVudGl0eS5ydW50aW1lSWRDb3VudCArPSAxbjtcbiAgICAgICAgc3VwZXIoe1xuICAgICAgICAgICAgd29ybGQsXG4gICAgICAgICAgICAuLi5vcHRpb25zLFxuICAgICAgICAgICAgcnVudGltZUlkOiBFbnRpdHkucnVudGltZUlkQ291bnRcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bm5lY2Vzc2FyeS1jb25kaXRpb25cbiAgICAgICAgaWYgKHdvcmxkKSBzdXBlci5zZXRXb3JsZCh3b3JsZCk7XG4gICAgfVxuXG4gICAgcHVibGljIGdldCBbU3ltYm9sLnRvU3RyaW5nVGFnXSgpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gYEVudGl0eSgke3RoaXMudG9TdHJpbmcoKX0pYDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0IHRvIGEgc3RyaW5nIHJlcHJlc2VudGF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBzdHJpbmcuXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIGNvbnNvbGUubG9nKGVudGl0eS50b1N0cmluZygpKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBwdWJsaWMgdG9TdHJpbmcoKSB7XG4gICAgICAgIHJldHVybiBgdXVpZDogwqdhJHt0aGlzLmdldFVVSUQoKX3Cp3IsIGlkOiDCp2Eke3RoaXMuZ2V0UnVudGltZUlkKCl9wqdyLCBuYW1lOiDCp2Ike3RoaXMuZ2V0TmFtZSgpfcKnciwgdHlwZTogwqdiJHt0aGlzLmdldFR5cGUoKX3Cp3IsICR7c3VwZXIudG9TdHJpbmcoKX1gO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgZW50aXR5J3MgcnVudGltZSBpZC5cbiAgICAgKiBAcmV0dXJucyB7YmlnaW50fSBUaGUgZW50aXR5J3MgcnVudGltZSBpZC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiBjb25zdCBlbnRpdHlJZCA9IGVudGl0eS5nZXRSdW50aW1lSWQoKTtcbiAgICAgKiBjb25zb2xlLmxvZyhlbnRpdHlJZCk7IC8vIEV4LiBPdXRwdXQ6IDFuXG4gICAgICogYGBgXG4gICAgICovXG4gICAgcHVibGljIGdldFJ1bnRpbWVJZCgpOiBiaWdpbnQge1xuICAgICAgICByZXR1cm4gdGhpcy5ydW50aW1lSWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IHRoZSBlbnRpdHkncyBVVUlELlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBlbnRpdHkncyBVVUlELlxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiBjb25zb2xlLmxvZyhlbnRpdHkuZ2V0VVVJRCgpKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0VVVJRCgpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gdGhpcy51dWlkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEZpcmVkIGV2ZXJ5IHRpY2sgZnJvbSB0aGUgZXZlbnQgc3Vic2NyaXB0aW9uIGluIHRoZSBjb25zdHJ1Y3Rvci5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gX3RpY2sgLSBUaGUgY3VycmVudCB3b3JsZC10aWNrLlxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSB1cGRhdGUgaXMgY29tcGxldGUuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogZW50aXR5LnVwZGF0ZSgxMCk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgcHVibGljIGFzeW5jIHVwZGF0ZShfdGljazogbnVtYmVyKTogUHJvbWlzZTx2b2lkPiB7fVxuXG4gICAgLyoqXG4gICAgICogR2V0IHRoZSBzZXJ2ZXIgaW5zdGFuY2UuXG4gICAgICogQHJldHVybnMge1NlcnZlcn0gVGhlIHNlcnZlciBpbnN0YW5jZS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiBjb25zdCBzZXJ2ZXIgPSBlbnRpdHkuZ2V0U2VydmVyKCk7XG4gICAgICogLy8gRG8gdGhpbmdzIHdpdGggdGhlIHNlcnZlci5cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0U2VydmVyKCk6IFNlcnZlciB7XG4gICAgICAgIHJldHVybiB0aGlzLnNlcnZlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTcGF3biB0aGUgZW50aXR5LlxuICAgICAqIEB0b2RvIGBtb3Rpb25gLCBgcGl0Y2hgICYgYHlhd2AgaXMgdW5pbXBsZW1lbnRlZC5cbiAgICAgKiBAcGFyYW0ge1BsYXllcn0gW3BsYXllcl0gLSBUaGUgcGxheWVyIHRvIHNlbmQgdGhlIHBhY2tldCB0by5cbiAgICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgZW50aXR5IGlzIHNwYXduZWQuXG4gICAgICovXG4gICAgcHVibGljIGFzeW5jIHNlbmRTcGF3bihwbGF5ZXI/OiBQbGF5ZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgY29uc3QgcGxheWVyczogUGxheWVyW10gPSBwbGF5ZXIgPyBbcGxheWVyXSA6IHRoaXMuZ2V0V29ybGQoKS5nZXRQbGF5ZXJzKCk7XG5cbiAgICAgICAgY29uc3QgcGFja2V0ID0gbmV3IEFkZEFjdG9yUGFja2V0KCk7XG4gICAgICAgIHBhY2tldC5ydW50aW1lRW50aXR5SWQgPSB0aGlzLmdldFJ1bnRpbWVJZCgpO1xuICAgICAgICBwYWNrZXQudHlwZSA9ICh0aGlzLmNvbnN0cnVjdG9yIGFzIGFueSkuTU9CX0lEOyAvLyBUT0RPXG4gICAgICAgIHBhY2tldC5wb3NpdGlvbiA9IHRoaXMuZ2V0UG9zaXRpb24oKTtcbiAgICAgICAgcGFja2V0Lm1vdGlvbiA9IG5ldyBWZWN0b3IzKDAsIDAsIDApOyAvLyBUT0RPOiBtb3Rpb25cbiAgICAgICAgcGFja2V0LnBpdGNoID0gdGhpcy5waXRjaDtcbiAgICAgICAgcGFja2V0LnlhdyA9IHRoaXMueWF3O1xuICAgICAgICBwYWNrZXQuaGVhZFlhdyA9IHRoaXMuaGVhZFlhdztcbiAgICAgICAgcGFja2V0Lm1ldGFkYXRhID0gdGhpcy5tZXRhZGF0YTtcbiAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwocGxheWVycy5tYXAoYXN5bmMgKHApID0+IHAuZ2V0TmV0d29ya1Nlc3Npb24oKS5zZW5kKHBhY2tldCkpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBEZXNwYXduIHRoZSBlbnRpdHkuXG4gICAgICogQHBhcmFtIHtQbGF5ZXJ9IFtwbGF5ZXJdIC0gVGhlIHBsYXllciB0byBzZW5kIHRoZSBwYWNrZXQgdG8sIGlmIG5vdCBzcGVjaWZpZWQsIGFsbCBwbGF5ZXJzIGluIHRoZSB3b3JsZCB3aWxsIHJlY2VpdmUgdGhlIHBhY2tldC5cbiAgICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgZW50aXR5IGlzIGRlc3Bhd25lZC5cbiAgICAgKi9cbiAgICBwdWJsaWMgYXN5bmMgc2VuZERlc3Bhd24ocGxheWVyPzogUGxheWVyKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGNvbnN0IHBsYXllcnM6IFBsYXllcltdID0gcGxheWVyID8gW3BsYXllcl0gOiB0aGlzLmdldFdvcmxkKCkuZ2V0UGxheWVycygpO1xuXG4gICAgICAgIGNvbnN0IHBhY2tldCA9IG5ldyBSZW1vdmVBY3RvclBhY2tldCgpO1xuICAgICAgICBwYWNrZXQudW5pcXVlRW50aXR5SWQgPSB0aGlzLnJ1bnRpbWVJZDtcbiAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwocGxheWVycy5tYXAoYXN5bmMgKHBsYXllcikgPT4gcGxheWVyLmdldE5ldHdvcmtTZXNzaW9uKCkuc2VuZChwYWNrZXQpKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VuZCB0aGUgcG9zaXRpb24gdG8gYWxsIHRoZSBwbGF5ZXJzIGluIHRoZSBzYW1lIHdvcmxkLlxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSBwb3NpdGlvbiBpcyBzZW50LlxuICAgICAqL1xuICAgIHB1YmxpYyBhc3luYyBzZW5kUG9zaXRpb24oKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgICAgICAgdGhpcy5nZXRXb3JsZCgpXG4gICAgICAgICAgICAgICAgLmdldFBsYXllcnMoKVxuICAgICAgICAgICAgICAgIC5tYXAoKHRhcmdldCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBwYWNrZXQgPSBuZXcgTW92ZUFjdG9yQWJzb2x1dGVQYWNrZXQoKTtcbiAgICAgICAgICAgICAgICAgICAgcGFja2V0LnJ1bnRpbWVFbnRpdHlJZCA9IHRoaXMucnVudGltZUlkO1xuICAgICAgICAgICAgICAgICAgICBwYWNrZXQucG9zaXRpb24gPSB0aGlzLmdldFBvc2l0aW9uKCk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0YXJnZXQuZ2V0TmV0d29ya1Nlc3Npb24oKS5zZW5kKHBhY2tldCk7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZW5kIGEgbWVzc2FnZSB0byBhbiBlbnRpdHkuXG4gICAgICogQHJlbWFya3MgVGhpcyB3aWxsIHNpbGVudGx5IGZhaWwgb24gbm9uLWNsaWVudC1jb250cm9sbGVkIGVudGl0aWVzLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlIC0gVGhlIG1lc3NhZ2UuXG4gICAgICogQHBhcmFtIHtUZXh0VHlwZX0gW3R5cGU9VGV4dFR5cGUuUmF3XSAtIFRoZSB0ZXh0IHR5cGUuXG4gICAgICogQGV4YW1wbGUgU2VuZCBcIkhlbGxvIFdvcmxkIVwiIHRvIGEgY2xpZW50OlxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiBlbnRpdHkuc2VuZE1lc3NhZ2UoJ0hlbGxvIFdvcmxkIScpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHB1YmxpYyBzZW5kTWVzc2FnZShtZXNzYWdlOiBzdHJpbmcsIHR5cGU6IFRleHRUeXBlID0gVGV4dFR5cGUuUmF3KTogdm9pZCB7XG4gICAgICAgIHRoaXMuc2VydmVyLmdldExvZ2dlcigpLndhcm4oYEVudGl0eS9zZW5kTWVzc2FnZSBpcyBub3QgaW1wbGVtZW50ZWQ6IChtZXNzYWdlOiAke21lc3NhZ2V9LCB0eXBlOiAke3R5cGV9KWApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldCB0aGUgYHhgIHBvc2l0aW9uLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB4IC0gVGhlIGB4YCBjb29yZGluYXRlLlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW3N1cHByZXNzPWZhbHNlXSAtIElmIHRydWUsIHRoZSBjbGllbnQgd29uJ3QgYmUgbm90aWZpZWQgYWJvdXQgdGhlIHBvc2l0aW9uIGNoYW5nZS5cbiAgICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgeCBwb3NpdGlvbiBpcyBzZXQuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogYXdhaXQgZW50aXR5LnNldFgoMTApO1xuICAgICAqIGBgYFxuICAgICAqIEByZW1hcmtzIFRoaXMgbWV0aG9kIHdpbGwgYWxzbyBzZW5kIHRoZSBwb3NpdGlvbiB1cGRhdGUgdG8gdGhlIGNsaWVudCBpZiBgc3VwcHJlc3NgIGlzIGBmYWxzZWAuXG4gICAgICovXG4gICAgcHVibGljIGFzeW5jIHNldFgoeDogbnVtYmVyLCBzdXBwcmVzcyA9IGZhbHNlKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHN1cGVyLnNldFguYmluZCh0aGlzKSh4KTtcbiAgICAgICAgaWYgKHN1cHByZXNzICYmICF0aGlzLmlzUGxheWVyKCkpIGF3YWl0IHRoaXMuc2VuZFBvc2l0aW9uKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0IHRoZSBgeWAgcG9zaXRpb24uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHkgLSBUaGUgYHlgIGNvb3JkaW5hdGUuXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbc3VwcHJlc3M9ZmFsc2VdIC0gSWYgdHJ1ZSwgdGhlIGNsaWVudCB3b24ndCBiZSBub3RpZmllZCBhYm91dCB0aGUgcG9zaXRpb24gY2hhbmdlLlxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSB5IHBvc2l0aW9uIGlzIHNldC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiBhd2FpdCBlbnRpdHkuc2V0WSgxMCk7XG4gICAgICogYGBgXG4gICAgICogQHJlbWFya3MgVGhpcyBtZXRob2Qgd2lsbCBhbHNvIHNlbmQgdGhlIHBvc2l0aW9uIHVwZGF0ZSB0byB0aGUgY2xpZW50IGlmIGBzdXBwcmVzc2AgaXMgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBwdWJsaWMgYXN5bmMgc2V0WSh5OiBudW1iZXIsIHN1cHByZXNzID0gZmFsc2UpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgc3VwZXIuc2V0WS5iaW5kKHRoaXMpKHkpO1xuICAgICAgICBpZiAoc3VwcHJlc3MgJiYgIXRoaXMuaXNQbGF5ZXIoKSkgYXdhaXQgdGhpcy5zZW5kUG9zaXRpb24oKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXQgdGhlIGB6YCBwb3NpdGlvbi5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0geiAtIFRoZSBgemAgY29vcmRpbmF0ZS5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtzdXBwcmVzcz1mYWxzZV0gLSBJZiB0cnVlLCB0aGUgY2xpZW50IHdvbid0IGJlIG5vdGlmaWVkIGFib3V0IHRoZSBwb3NpdGlvbiBjaGFuZ2UuXG4gICAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gdGhlIHogcG9zaXRpb24gaXMgc2V0LlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIGF3YWl0IGVudGl0eS5zZXRaKDEwKTtcbiAgICAgKiBgYGBcbiAgICAgKiBAcmVtYXJrcyBUaGlzIG1ldGhvZCB3aWxsIGFsc28gc2VuZCB0aGUgcG9zaXRpb24gdXBkYXRlIHRvIHRoZSBjbGllbnQgaWYgYHN1cHByZXNzYCBpcyBgZmFsc2VgLlxuICAgICAqL1xuICAgIHB1YmxpYyBhc3luYyBzZXRaKHo6IG51bWJlciwgc3VwcHJlc3MgPSBmYWxzZSk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBzdXBlci5zZXRaLmJpbmQodGhpcykoeik7XG4gICAgICAgIGlmIChzdXBwcmVzcyAmJiAhdGhpcy5pc1BsYXllcigpKSBhd2FpdCB0aGlzLnNlbmRQb3NpdGlvbigpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldCB0aGUgZW50aXR5J3MgcG9zaXRpb24gYW5kIG5vdGlmeSB0aGUgY2xpZW50cy5cbiAgICAgKiBAcGFyYW0ge29iamVjdH0gb3B0aW9ucyAtIFRoZSBwb3NpdGlvbiBvcHRpb25zLlxuICAgICAqIEBwYXJhbSB7VmVjdG9yM30gb3B0aW9ucy5wb3NpdGlvbiAtIFRoZSBwb3NpdGlvbi5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW29wdGlvbnMucGl0Y2hdIC0gVGhlIHBpdGNoLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbb3B0aW9ucy55YXddIC0gVGhlIHlhdy5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW29wdGlvbnMuaGVhZFlhd10gLSBUaGUgaGVhZCB5YXcuXG4gICAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gdGhlIHBvc2l0aW9uIGlzIHNldC5cbiAgICAgKi9cbiAgICBwdWJsaWMgYXN5bmMgc2V0UG9zaXRpb24oe1xuICAgICAgICBwb3NpdGlvbixcbiAgICAgICAgcGl0Y2ggPSB0aGlzLnBpdGNoLFxuICAgICAgICB5YXcgPSB0aGlzLnlhdyxcbiAgICAgICAgaGVhZFlhdyA9IHRoaXMuaGVhZFlhd1xuICAgIH06IHtcbiAgICAgICAgcG9zaXRpb246IFZlY3RvcjM7XG4gICAgICAgIHBpdGNoPzogbnVtYmVyO1xuICAgICAgICB5YXc/OiBudW1iZXI7XG4gICAgICAgIGhlYWRZYXc/OiBudW1iZXI7XG4gICAgfSk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICB0aGlzLnBpdGNoID0gcGl0Y2g7XG4gICAgICAgIHRoaXMueWF3ID0geWF3O1xuICAgICAgICB0aGlzLmhlYWRZYXcgPSBoZWFkWWF3O1xuXG4gICAgICAgIGF3YWl0IHN1cGVyLnNldFgocG9zaXRpb24uZ2V0WCgpKTtcbiAgICAgICAgYXdhaXQgc3VwZXIuc2V0WShwb3NpdGlvbi5nZXRZKCkpO1xuICAgICAgICBhd2FpdCBzdXBlci5zZXRaKHBvc2l0aW9uLmdldFooKSk7XG5cbiAgICAgICAgYXdhaXQgdGhpcy5zZW5kUG9zaXRpb24oKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVjayBpZiB0aGUgZW50aXR5IGlzIGEgcGxheWVyLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBgdHJ1ZWAgaWYgdGhlIGVudGl0eSBpcyBwbGF5ZXItY29udHJvbGxlZCwgb3RoZXJ3aXNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogaWYgKGVudGl0eS5pc1BsYXllcigpKSB7XG4gICAgICogICAgIGNvbnNvbGUubG9nKCdFbnRpdHkgaXMgYSBwbGF5ZXInKTtcbiAgICAgKiB9IGVsc2Uge1xuICAgICAqICAgICBjb25zb2xlLmxvZygnRW50aXR5IGlzIG5vdCBhIHBsYXllcicpO1xuICAgICAqIH1cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBwdWJsaWMgaXNQbGF5ZXIoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVjayBpZiB0aGUgZW50aXR5IGlzIGEgY29uc29sZSBpbnN0YW5jZS5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gYHRydWVgIGlmIHRoZSBlbnRpdHkgaXMgY29uc29sZS1jb250cm9sbGVkLCBvdGhlcndpc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiBpZiAoZW50aXR5LmlzQ29uc29sZSgpKSB7XG4gICAgICogICAgIGNvbnNvbGUubG9nKCdFbnRpdHkgaXMgYSBjb25zb2xlJyk7XG4gICAgICogfSBlbHNlIHtcbiAgICAgKiAgICAgY29uc29sZS5sb2coJ0VudGl0eSBpcyBub3QgYSBjb25zb2xlJyk7XG4gICAgICogfVxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHB1YmxpYyBpc0NvbnNvbGUoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldFJ1bnRpbWVJZCgpIDw9IDBuO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgZW50aXR5J3MgKHBvdGVudGlhbGx5IGN1c3RvbSkgbmFtZS5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgZW50aXR5J3MgbmFtZSB3aXRob3V0IGZvcm1hdHRpbmcgKHVzdWFsbHkgcHJlZml4ICYgc3VmZml4KS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiBjb25zdCBuYW1lID0gZW50aXR5LmdldE5hbWUoKTtcbiAgICAgKiBjb25zb2xlLmxvZyhgRW50aXR5IG5hbWU6ICR7bmFtZX1gKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0TmFtZSgpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRGb3JtYXR0ZWRVc2VybmFtZSgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldCB0aGUgZW50aXR5J3MgbmFtZS5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZSAtIFRoZSBuYW1lLlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIGVudGl0eS5zZXROYW1lKCdNci4gU2hlZXAnKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBwdWJsaWMgc2V0TmFtZShuYW1lOiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5tZXRhZGF0YS5zZXROYW1lVGFnKG5hbWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgZW50aXR5J3MgZm9ybWF0dGVkIG5hbWUuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gVGhlIGVudGl0eSdzIGZvcm1hdHRlZCBuYW1lIChpbmNsdWRpbmcgcHJlZml4ICYgc3VmZml4KS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiBjb25zdCBmb3JtYXR0ZWROYW1lID0gZW50aXR5LmdldEZvcm1hdHRlZFVzZXJuYW1lKCk7XG4gICAgICogY29uc29sZS5sb2coYEVudGl0eSBmb3JtYXR0ZWQgbmFtZTogJHtmb3JtYXR0ZWROYW1lfWApOyAvLyBFbnRpdHkgZm9ybWF0dGVkIG5hbWU6IFNoZWVwXG4gICAgICogYGBgXG4gICAgICovXG4gICAgcHVibGljIGdldEZvcm1hdHRlZFVzZXJuYW1lKCk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICB0aGlzLm1ldGFkYXRhLmdldFN0cmluZyhNZXRhZGF0YUZsYWcuTkFNRVRBRykgfHxcbiAgICAgICAgICAgIC8vIFJlcGxhY2UgYWxsICdfJyB3aXRoIGEgJyAnIGFuZCBjYXBpdGFsaXplIGVhY2ggd29yZCBhZnRlcndhcmRzLFxuICAgICAgICAgICAgLy8gc2hvdWxkIHByb2JhYmx5IGJlIHJlcGxhY2VkIHdpdGggcmVnZXguXG4gICAgICAgICAgICAoKCh0aGlzLmNvbnN0cnVjdG9yIGFzIGFueSk/Lk1PQl9JRCBhcyBzdHJpbmcpIHx8ICdVbmtub3duIEVudGl0eScpXG4gICAgICAgICAgICAgICAgLnNwbGl0KCc6JylbMV0hXG4gICAgICAgICAgICAgICAgLnJlcGxhY2VBbGwoJ18nLCAnICcpXG4gICAgICAgICAgICAgICAgLnNwbGl0KCcgJylcbiAgICAgICAgICAgICAgICAubWFwKCh3b3JkKSA9PiB3b3JkWzBdIS50b1VwcGVyQ2FzZSgpICsgd29yZC5zbGljZSgxLCB3b3JkLmxlbmd0aCkpXG4gICAgICAgICAgICAgICAgLmpvaW4oJyAnKVxuICAgICAgICApO1xuICAgIH1cbn1cbiJdLCJuYW1lcyI6WyJjbG9zZXN0IiwicGxheWVyIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7O0FBa0JPLE1BQU0sbUJBQW1CLFFBQVMsQ0FBQTtBQUFBLEVBQ2xCLElBQUE7QUFBQSxFQUNBLFNBQUE7QUFBQSxFQUNBLE1BQUE7QUFBQSxFQUVaLEtBQUE7QUFBQSxFQUNBLEdBQUE7QUFBQSxFQUNBLE9BQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQWNBLFdBQVksQ0FBQTtBQUFBLElBQ2YsSUFBQTtBQUFBLElBQ0EsU0FBQTtB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