@jsprismarine/prismarine
Version:
Dedicated Minecraft Bedrock Edition server written in TypeScript
421 lines (417 loc) • 52.8 kB
JavaScript
'use strict';
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: 'Module' } });
const math = require('@jsprismarine/math');
const minecraft = require('@jsprismarine/minecraft');
const chat_Chat = require('./chat/Chat.cjs.cjs');
const entity_Human = require('./entity/Human.cjs.cjs');
const events_chat_ChatEvent = require('./events/chat/ChatEvent.cjs.cjs');
const events_player_PlayerSetGamemodeEvent = require('./events/player/PlayerSetGamemodeEvent.cjs.cjs');
const events_player_PlayerToggleFlightEvent = require('./events/player/PlayerToggleFlightEvent.cjs.cjs');
const events_player_PlayerToggleSprintEvent = require('./events/player/PlayerToggleSprintEvent.cjs.cjs');
require('./network/packet/ActorFallPacket.cjs.cjs');
require('./network/packet/AddActorPacket.cjs.cjs');
require('./network/packet/AddItemActorPacket.cjs.cjs');
require('./network/packet/AddPlayerPacket.cjs.cjs');
require('./network/packet/AnimatePacket.cjs.cjs');
require('./network/packet/AvailableActorIdentifiersPacket.cjs.cjs');
require('./network/packet/AvailableCommandsPacket.cjs.cjs');
require('@jsprismarine/jsbinaryutils');
require('zlib');
require('./network/CompressionProvider.cjs.cjs');
require('./network/packet/NetworkSettingsPacket.cjs.cjs');
require('./network/packet/BiomeDefinitionListPacket.cjs.cjs');
const network_packet_ChangeDimensionPacket = require('./network/packet/ChangeDimensionPacket.cjs.cjs');
require('./network/packet/ChunkRadiusUpdatedPacket.cjs.cjs');
require('./network/packet/CommandRequestPacket.cjs.cjs');
require('./network/packet/ContainerClosePacket.cjs.cjs');
require('./network/packet/ContainerOpenPacket.cjs.cjs');
require('./network/packet/CreativeContentPacket.cjs.cjs');
require('./network/packet/DisconnectPacket.cjs.cjs');
require('./network/packet/EmoteListPacket.cjs.cjs');
require('./network/packet/InteractPacket.cjs.cjs');
require('./network/packet/InventoryContentPacket.cjs.cjs');
require('./network/packet/InventoryTransactionPacket.cjs.cjs');
require('./network/packet/ItemComponentPacket.cjs.cjs');
require('./network/packet/ItemStackRequestPacket.cjs.cjs');
require('./network/packet/ItemStackResponsePacket.cjs.cjs');
require('./network/packet/LevelChunkPacket.cjs.cjs');
require('./network/packet/LevelSoundEventPacket.cjs.cjs');
require('./network/packet/LoginPacket.cjs.cjs');
require('./network/packet/MobEquipmentPacket.cjs.cjs');
require('./network/packet/MoveActorAbsolutePacket.cjs.cjs');
require('./network/packet/MovePlayerPacket.cjs.cjs');
require('./network/packet/NetworkChunkPublisherUpdatePacket.cjs.cjs');
require('./network/packet/OnScreenTextureAnimationPacket.cjs.cjs');
require('./network/packet/PacketViolationWarningPacket.cjs.cjs');
require('./network/packet/PlaySoundPacket.cjs.cjs');
require('./network/packet/PlayStatusPacket.cjs.cjs');
require('./network/packet/PlayerActionPacket.cjs.cjs');
require('./network/packet/PlayerListPacket.cjs.cjs');
require('./network/packet/PlayerSkinPacket.cjs.cjs');
require('./network/packet/RemoveActorPacket.cjs.cjs');
require('./network/packet/RequestChunkRadiusPacket.cjs.cjs');
require('./network/packet/RequestNetworkSettingsPacket.cjs.cjs');
require('./network/packet/ResourcePackResponsePacket.cjs.cjs');
require('./network/packet/ResourcePackStackPacket.cjs.cjs');
require('./network/packet/ResourcePacksInfoPacket.cjs.cjs');
require('./network/packet/ServerSettingsRequestPacket.cjs.cjs');
require('./network/packet/SetActorDataPacket.cjs.cjs');
require('./network/packet/SetDefaultGametypePacket.cjs.cjs');
require('./network/packet/SetHealthPacket.cjs.cjs');
require('./network/packet/SetLocalPlayerAsInitializedPacket.cjs.cjs');
require('./network/packet/SetPlayerGametypePacket.cjs.cjs');
require('./network/packet/SetTimePacket.cjs.cjs');
require('./network/packet/ShowProfilePacket.cjs.cjs');
require('./network/packet/StartGamePacket.cjs.cjs');
require('./network/packet/TextPacket.cjs.cjs');
require('./network/packet/TickSyncPacket.cjs.cjs');
require('./network/packet/TransferPacket.cjs.cjs');
require('./network/packet/UpdateAdventureSettingsPacket.cjs.cjs');
require('./network/packet/UpdateAttributesPacket.cjs.cjs');
require('./network/packet/UpdateBlockPacket.cjs.cjs');
require('./network/packet/WorldEventPacket.cjs.cjs');
const network_PlayerSession = require('./network/PlayerSession.cjs.cjs');
const network_type_MovementType = require('./network/type/MovementType.cjs.cjs');
const network_type_PlayStatusType = require('./network/type/PlayStatusType.cjs.cjs');
const network_type_TextType = require('./network/type/TextType.cjs.cjs');
const utils_Timer = require('./utils/Timer.cjs.cjs');
const world_CoordinateUtils = require('./world/CoordinateUtils.cjs.cjs');
const VANILLA_DEFAULT_SPAWN_RADIUS = 4;
class Player extends entity_Human.default {
address;
networkSession;
permissions;
/**
* Timer used for various metrics.
*/
timer;
connected = false;
xuid = "";
randomId = 0;
locale = "";
skin = null;
viewDistance = 0;
gamemode = minecraft.Gametype.WORLD_DEFAULT;
onGround = false;
flying = false;
sneaking = false;
platformChatId = "";
// TODO: read this value from Login
device = null;
chunkSendQueue = /* @__PURE__ */ new Set();
/**
* Player's constructor.
*/
constructor({
connection,
world,
server,
uuid
}) {
super({
world,
server,
uuid
});
this.timer = new utils_Timer.default();
this.address = connection.getRakNetSession().getAddress();
this.networkSession = new network_PlayerSession.default(server, connection, this);
this.permissions = [];
this.server.on("chat", this.chatHandler.bind(this));
}
/**
* On enable hook.
* @group Lifecycle
*/
async enable() {
const playerData = await this.getWorld().getPlayerData(this);
this.permissions = await this.server.getPermissionManager().getPermissions(this);
this.gamemode = minecraft.getGametypeId(playerData.gamemode || this.server.getConfig().getGamemode());
this.setPosition({
position: playerData.position ? math.Vector3.fromObject(playerData.position) : await this.getWorld().getSpawnPosition(),
pitch: playerData.position?.pitch || 0,
yaw: playerData.position?.yaw || 0,
headYaw: playerData.position?.headYaw || 0,
type: network_type_MovementType.default.Reset
});
await this.sendPosition();
await this.sendSettings();
await Promise.all(
this.getWorld().getPlayers().map((target) => this.getNetworkSession().broadcastMove(target, network_type_MovementType.default.Reset))
);
this.server.getLogger().debug(`(Complete player creation took ${this.timer.stop()} ms)`);
this.connected = true;
}
/**
* On disable hook.
* @group Lifecycle
*/
async disable() {
if (this.connected && this.xuid) await this.getWorld().savePlayerData(this);
await this.getWorld().removeEntity(this);
await this.getNetworkSession().removeFromPlayerList();
for (const onlinePlayer of this.server.getSessionManager().getAllPlayers()) {
await this.getNetworkSession().sendDespawn(onlinePlayer);
}
const event = new events_chat_ChatEvent.default(
new chat_Chat.Chat({
sender: this.server.getConsole(),
message: `§e%multiplayer.player.left`,
parameters: [this.getName()],
needsTranslation: true,
type: chat_Chat.ChatType.TRANSLATION
})
);
await this.server.emit("chat", event);
this.connected = false;
this.server.removeListener("chat", this.chatHandler);
}
async chatHandler(evt) {
if (evt.isCancelled()) return;
if (evt.getChat().getChannel() === "*.everyone" || evt.getChat().getChannel() === "*.ops" && this.isOp() || evt.getChat().getChannel() === `*.player.${this.getName()}`)
await this.sendMessage(
evt.getChat().getMessage(),
evt.getChat().getType(),
evt.getChat().getParameters(),
evt.getChat().isNeedsTranslation()
);
}
/**
* Used to match vanilla behavior, will send chunks
* with an initial view radius of VANILLA_DEFAULT_SPAWN_RADIUS.
*/
async sendInitialSpawnChunks() {
const minX = world_CoordinateUtils.default.fromBlockToChunk(this.x) - VANILLA_DEFAULT_SPAWN_RADIUS;
const minZ = world_CoordinateUtils.default.fromBlockToChunk(this.z) - VANILLA_DEFAULT_SPAWN_RADIUS;
const maxX = world_CoordinateUtils.default.fromBlockToChunk(this.x) + VANILLA_DEFAULT_SPAWN_RADIUS;
const maxZ = world_CoordinateUtils.default.fromBlockToChunk(this.z) + VANILLA_DEFAULT_SPAWN_RADIUS;
const savedChunks = [];
const sendQueue = [];
for (let chunkX = minX; chunkX <= maxX; ++chunkX) {
for (let chunkZ = minZ; chunkZ <= maxZ; ++chunkZ) {
savedChunks.push({ x: chunkX, z: chunkZ });
sendQueue.push(this.getWorld().getChunk(chunkX, chunkZ));
}
}
await this.networkSession.sendNetworkChunkPublisher(VANILLA_DEFAULT_SPAWN_RADIUS, savedChunks);
const getUniqueChunks = (sendList) => {
const xSet = /* @__PURE__ */ new Set();
const zSet = /* @__PURE__ */ new Set();
for (const coord of sendList) {
xSet.add(coord.x);
zSet.add(coord.z);
}
return Math.floor((xSet.size + zSet.size) / 2);
};
for (let i = 0; i < getUniqueChunks(savedChunks); ++i) {
await this.networkSession.sendNetworkChunkPublisher(VANILLA_DEFAULT_SPAWN_RADIUS, []);
}
for await (const chunk of sendQueue) {
await this.networkSession.sendChunk(chunk);
}
}
/**
* Change the player's current world.
* @param {World} world - the new world
*/
async setWorld(world) {
const dim0 = new network_packet_ChangeDimensionPacket.default();
dim0.dimension = 0;
dim0.position = this.getPosition();
dim0.respawn = false;
const dim1 = new network_packet_ChangeDimensionPacket.default();
dim1.dimension = 1;
dim1.position = this.getPosition();
dim1.respawn = false;
await this.sendDespawn();
await this.getWorld().removeEntity(this);
await super.setWorld(world);
await world.addEntity(this);
await this.networkSession.send(dim0);
await this.networkSession.sendPlayStatus(network_type_PlayStatusType.default.PlayerSpawn);
await this.networkSession.send(dim1);
await this.networkSession.sendPlayStatus(network_type_PlayStatusType.default.PlayerSpawn);
await this.sendInitialSpawnChunks();
await this.networkSession.send(dim1);
await this.networkSession.sendPlayStatus(network_type_PlayStatusType.default.PlayerSpawn);
await this.networkSession.send(dim0);
await this.networkSession.sendPlayStatus(network_type_PlayStatusType.default.PlayerSpawn);
await this.networkSession.clearChunks();
await this.networkSession.needNewChunks();
await this.networkSession.sendPlayStatus(network_type_PlayStatusType.default.PlayerSpawn);
}
isOnline() {
return this.connected;
}
async update(tick) {
await super.update(tick);
await this.networkSession.update(tick);
if (tick % (20 * 5 * 60 * 1) === 0) {
await this.networkSession.sendTime(tick);
}
for (const chunk of this.chunkSendQueue) {
await this.networkSession.sendNetworkChunkPublisher(this.viewDistance || VANILLA_DEFAULT_SPAWN_RADIUS, []);
await this.networkSession.sendChunk(chunk);
this.chunkSendQueue.delete(chunk);
}
}
async kick(reason = "unknown reason") {
await this.disable();
await this.networkSession.kick(reason);
this.server.getLogger().verbose(`Player with id §b${this.getRuntimeId()}§r was kicked: ${reason}`);
}
async sendSettings() {
await this.getNetworkSession().sendGamemode();
await Promise.all(
this.server.getSessionManager().getAllPlayers().map(async (target) => {
await target.getNetworkSession().sendAbilities(this);
await target.getNetworkSession().sendSettings(this);
})
);
}
/**
* Player spawning logic.
*/
async sendSpawn() {
await this.sendPosition();
await this.setGamemode();
await this.getNetworkSession().sendInventory();
await this.sendSettings();
}
async sendDespawn() {
}
/**
* Send a chat message to the client.
* @param message - the message
*/
async sendMessage(message, type = network_type_TextType.default.Raw, parameters = [], needsTranslation = false) {
await this.networkSession.sendMessage({
message,
parameters,
needsTranslation,
type
});
}
async setGamemode(mode) {
mode ??= this.gamemode;
const event = new events_player_PlayerSetGamemodeEvent.default(this, mode);
this.server.post(["playerSetGamemode", event]);
if (event.isCancelled()) return;
this.gamemode = event.getGamemode();
await this.networkSession.sendGamemode();
if (this.gamemode === minecraft.Gametype.CREATIVE || this.gamemode === minecraft.Gametype.SPECTATOR) {
this.metadata.setCanFly(true);
} else {
this.metadata.setCanFly(false);
await this.setFlying(false);
}
await this.sendSettings();
await this.networkSession.sendGamemode();
await this.networkSession.sendMetadata();
}
getNetworkSession() {
return this.networkSession;
}
getAddress() {
return this.address;
}
getName() {
return this.metadata.nameTag;
}
getFormattedUsername() {
return `<${this.getName()}>`;
}
getPermissions() {
return this.permissions;
}
/**
* Get the XUID of the player.
* @returns {string | null} XUID of the player or null if not available
*/
getXUID() {
return this.xuid || null;
}
isPlayer() {
return true;
}
/**
* Check if the `Player` is an operator.
* @returns `true` if this player is an operator otherwise `false`.
*/
isOp() {
return this.server.getPermissionManager().isOp(this.getName());
}
async setSprinting(sprinting) {
if (sprinting === this.metadata.sprinting) return;
const event = new events_player_PlayerToggleSprintEvent.default(this, sprinting);
this.server.post(["playerToggleSprint", event]);
if (event.isCancelled()) return;
this.metadata.setSprinting(event.getIsSprinting());
await this.networkSession.sendMetadata();
}
isFlying() {
return this.flying;
}
async setFlying(flying) {
if (flying === this.isFlying()) return;
if (!this.metadata.canFly) {
this.flying = false;
await this.sendSettings();
return;
}
const event = new events_player_PlayerToggleFlightEvent.default(this, flying);
this.server.post(["playerToggleFlight", event]);
if (event.isCancelled()) return;
this.flying = event.getIsFlying();
await this.sendSettings();
}
isSneaking() {
return this.sneaking;
}
async setSneaking(val) {
if (val === this.sneaking) return;
this.sneaking = val;
}
isOnGround() {
return this.onGround;
}
async setOnGround(val) {
if (val === this.onGround) return;
this.onGround = val;
}
/**
* Set the position.
* @param {object} options - The options to set the position.
* @param {Vector3} options.position - The new position.
* @param {MovementType} [options.type=MovementType.Normal] - The movement type.
* @param {number} [options.pitch=this.pitch] - The new pitch.
* @param {number} [options.yaw=this.yaw] - The new yaw.
* @param {number} [options.headYaw=this.headYaw] - The new head yaw.
* @param {boolean} [broadcast=true] - Whether to broadcast the position change.
* @remarks This will notify the player's client about the position change.
*/
async setPosition({
position,
type = network_type_MovementType.default.Normal,
pitch = this.pitch,
yaw = this.yaw,
headYaw = this.headYaw
}, broadcast = true) {
await super.setPosition({ position });
this.pitch = pitch;
this.yaw = yaw;
this.headYaw = headYaw;
if (!broadcast) return;
await this.networkSession.broadcastMove(this, type);
}
/**
* 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 super.sendPosition();
}
}
exports.VANILLA_DEFAULT_SPAWN_RADIUS = VANILLA_DEFAULT_SPAWN_RADIUS;
exports.default = Player;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUGxheWVyLmNqcy5janMiLCJzb3VyY2VzIjpbIi4uL3NyYy9QbGF5ZXIudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgVmVjdG9yMyB9IGZyb20gJ0Bqc3ByaXNtYXJpbmUvbWF0aCc7XG5pbXBvcnQgeyBHYW1ldHlwZSwgZ2V0R2FtZXR5cGVJZCB9IGZyb20gJ0Bqc3ByaXNtYXJpbmUvbWluZWNyYWZ0JztcbmltcG9ydCB0eXBlIHsgSW5ldEFkZHJlc3MgfSBmcm9tICdAanNwcmlzbWFyaW5lL3Jha25ldCc7XG5pbXBvcnQgdHlwZSBTZXJ2ZXIgZnJvbSAnLi9TZXJ2ZXInO1xuaW1wb3J0IHsgQ2hhdCwgQ2hhdFR5cGUgfSBmcm9tICcuL2NoYXQvQ2hhdCc7XG5pbXBvcnQgSHVtYW4gZnJvbSAnLi9lbnRpdHkvSHVtYW4nO1xuaW1wb3J0IENoYXRFdmVudCBmcm9tICcuL2V2ZW50cy9jaGF0L0NoYXRFdmVudCc7XG5pbXBvcnQgUGxheWVyU2V0R2FtZW1vZGVFdmVudCBmcm9tICcuL2V2ZW50cy9wbGF5ZXIvUGxheWVyU2V0R2FtZW1vZGVFdmVudCc7XG5pbXBvcnQgUGxheWVyVG9nZ2xlRmxpZ2h0RXZlbnQgZnJvbSAnLi9ldmVudHMvcGxheWVyL1BsYXllclRvZ2dsZUZsaWdodEV2ZW50JztcbmltcG9ydCBQbGF5ZXJUb2dnbGVTcHJpbnRFdmVudCBmcm9tICcuL2V2ZW50cy9wbGF5ZXIvUGxheWVyVG9nZ2xlU3ByaW50RXZlbnQnO1xuaW1wb3J0IHR5cGUgQ2xpZW50Q29ubmVjdGlvbiBmcm9tICcuL25ldHdvcmsvQ2xpZW50Q29ubmVjdGlvbic7XG5pbXBvcnQgeyBDaGFuZ2VEaW1lbnNpb25QYWNrZXQgfSBmcm9tICcuL25ldHdvcmsvUGFja2V0cyc7XG5pbXBvcnQgUGxheWVyU2Vzc2lvbiBmcm9tICcuL25ldHdvcmsvUGxheWVyU2Vzc2lvbic7XG5pbXBvcnQgdHlwZSB7IENodW5rQ29vcmQgfSBmcm9tICcuL25ldHdvcmsvcGFja2V0L05ldHdvcmtDaHVua1B1Ymxpc2hlclVwZGF0ZVBhY2tldCc7XG5pbXBvcnQgTW92ZW1lbnRUeXBlIGZyb20gJy4vbmV0d29yay90eXBlL01vdmVtZW50VHlwZSc7XG5pbXBvcnQgUGxheVN0YXR1c1R5cGUgZnJvbSAnLi9uZXR3b3JrL3R5cGUvUGxheVN0YXR1c1R5cGUnO1xuaW1wb3J0IFRleHRUeXBlIGZyb20gJy4vbmV0d29yay90eXBlL1RleHRUeXBlJztcbmltcG9ydCB0eXBlIERldmljZSBmcm9tICcuL3V0aWxzL0RldmljZSc7XG5pbXBvcnQgVGltZXIgZnJvbSAnLi91dGlscy9UaW1lcic7XG5pbXBvcnQgdHlwZSBTa2luIGZyb20gJy4vdXRpbHMvc2tpbi9Ta2luJztcbmltcG9ydCB0eXBlIHsgV29ybGQgfSBmcm9tICcuL3dvcmxkLyc7XG5pbXBvcnQgQ29vcmRpbmF0ZVV0aWxzIGZyb20gJy4vd29ybGQvQ29vcmRpbmF0ZVV0aWxzJztcbmltcG9ydCB0eXBlIENodW5rIGZyb20gJy4vd29ybGQvY2h1bmsvQ2h1bmsnO1xuXG4vKipcbiAqIERlZmF1bHQgc3Bhd24gdmlldyBkaXN0YW5jZSB1c2VkIGluIHZhbmlsbGFcbiAqL1xuZXhwb3J0IGNvbnN0IFZBTklMTEFfREVGQVVMVF9TUEFXTl9SQURJVVMgPSA0O1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBQbGF5ZXIgZXh0ZW5kcyBIdW1hbiB7XG4gICAgcHJpdmF0ZSByZWFkb25seSBhZGRyZXNzOiBJbmV0QWRkcmVzcztcbiAgICBwcml2YXRlIHJlYWRvbmx5IG5ldHdvcmtTZXNzaW9uOiBQbGF5ZXJTZXNzaW9uO1xuICAgIHByaXZhdGUgcGVybWlzc2lvbnM6IHN0cmluZ1tdO1xuXG4gICAgLyoqXG4gICAgICogVGltZXIgdXNlZCBmb3IgdmFyaW91cyBtZXRyaWNzLlxuICAgICAqL1xuICAgIHByaXZhdGUgdGltZXI6IFRpbWVyO1xuICAgIHByaXZhdGUgY29ubmVjdGVkID0gZmFsc2U7XG5cbiAgICBwdWJsaWMgeHVpZCA9ICcnO1xuICAgIHB1YmxpYyByYW5kb21JZCA9IDA7XG5cbiAgICBwdWJsaWMgbG9jYWxlID0gJyc7XG4gICAgcHVibGljIHNraW46IFNraW4gfCBudWxsID0gbnVsbDtcblxuICAgIHB1YmxpYyB2aWV3RGlzdGFuY2UgPSAwO1xuICAgIHB1YmxpYyBnYW1lbW9kZTogR2FtZXR5cGUgPSBHYW1ldHlwZS5XT1JMRF9ERUZBVUxUO1xuXG4gICAgcHJpdmF0ZSBvbkdyb3VuZCA9IGZhbHNlO1xuICAgIHByaXZhdGUgZmx5aW5nID0gZmFsc2U7XG4gICAgcHJpdmF0ZSBzbmVha2luZyA9IGZhbHNlO1xuXG4gICAgcHVibGljIHBsYXRmb3JtQ2hhdElkID0gJyc7IC8vIFRPRE86IHJlYWQgdGhpcyB2YWx1ZSBmcm9tIExvZ2luXG4gICAgcHVibGljIGRldmljZTogRGV2aWNlIHwgbnVsbCA9IG51bGw7XG5cbiAgICBwdWJsaWMgcmVhZG9ubHkgY2h1bmtTZW5kUXVldWUgPSBuZXcgU2V0PENodW5rPigpO1xuXG4gICAgLyoqXG4gICAgICogUGxheWVyJ3MgY29uc3RydWN0b3IuXG4gICAgICovXG4gICAgcHVibGljIGNvbnN0cnVjdG9yKHtcbiAgICAgICAgY29ubmVjdGlvbixcbiAgICAgICAgd29ybGQsXG4gICAgICAgIHNlcnZlcixcbiAgICAgICAgdXVpZFxuICAgIH06IHtcbiAgICAgICAgY29ubmVjdGlvbjogQ2xpZW50Q29ubmVjdGlvbjtcbiAgICAgICAgd29ybGQ6IFdvcmxkO1xuICAgICAgICBzZXJ2ZXI6IFNlcnZlcjtcbiAgICAgICAgdXVpZD86IHN0cmluZztcbiAgICB9KSB7XG4gICAgICAgIHN1cGVyKHtcbiAgICAgICAgICAgIHdvcmxkLFxuICAgICAgICAgICAgc2VydmVyLFxuICAgICAgICAgICAgdXVpZFxuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLnRpbWVyID0gbmV3IFRpbWVyKCk7XG5cbiAgICAgICAgdGhpcy5hZGRyZXNzID0gY29ubmVjdGlvbi5nZXRSYWtOZXRTZXNzaW9uKCkuZ2V0QWRkcmVzcygpO1xuICAgICAgICB0aGlzLm5ldHdvcmtTZXNzaW9uID0gbmV3IFBsYXllclNlc3Npb24oc2VydmVyLCBjb25uZWN0aW9uLCB0aGlzKTtcbiAgICAgICAgdGhpcy5wZXJtaXNzaW9ucyA9IFtdO1xuXG4gICAgICAgIHRoaXMuc2VydmVyLm9uKCdjaGF0JywgdGhpcy5jaGF0SGFuZGxlci5iaW5kKHRoaXMpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBPbiBlbmFibGUgaG9vay5cbiAgICAgKiBAZ3JvdXAgTGlmZWN5Y2xlXG4gICAgICovXG4gICAgcHVibGljIGFzeW5jIGVuYWJsZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgY29uc3QgcGxheWVyRGF0YSA9IGF3YWl0IHRoaXMuZ2V0V29ybGQoKS5nZXRQbGF5ZXJEYXRhKHRoaXMpO1xuXG4gICAgICAgIHRoaXMucGVybWlzc2lvbnMgPSBhd2FpdCB0aGlzLnNlcnZlci5nZXRQZXJtaXNzaW9uTWFuYWdlcigpLmdldFBlcm1pc3Npb25zKHRoaXMpO1xuICAgICAgICB0aGlzLmdhbWVtb2RlID0gZ2V0R2FtZXR5cGVJZChwbGF5ZXJEYXRhLmdhbWVtb2RlIHx8IHRoaXMuc2VydmVyLmdldENvbmZpZygpLmdldEdhbWVtb2RlKCkpO1xuXG4gICAgICAgIHRoaXMuc2V0UG9zaXRpb24oe1xuICAgICAgICAgICAgcG9zaXRpb246IHBsYXllckRhdGEucG9zaXRpb25cbiAgICAgICAgICAgICAgICA/IFZlY3RvcjMuZnJvbU9iamVjdChwbGF5ZXJEYXRhLnBvc2l0aW9uKVxuICAgICAgICAgICAgICAgIDogYXdhaXQgdGhpcy5nZXRXb3JsZCgpLmdldFNwYXduUG9zaXRpb24oKSxcbiAgICAgICAgICAgIHBpdGNoOiBwbGF5ZXJEYXRhLnBvc2l0aW9uPy5waXRjaCB8fCAwLFxuICAgICAgICAgICAgeWF3OiBwbGF5ZXJEYXRhLnBvc2l0aW9uPy55YXcgfHwgMCxcbiAgICAgICAgICAgIGhlYWRZYXc6IHBsYXllckRhdGEucG9zaXRpb24/LmhlYWRZYXcgfHwgMCxcbiAgICAgICAgICAgIHR5cGU6IE1vdmVtZW50VHlwZS5SZXNldFxuICAgICAgICB9KTtcbiAgICAgICAgYXdhaXQgdGhpcy5zZW5kUG9zaXRpb24oKTtcblxuICAgICAgICBhd2FpdCB0aGlzLnNlbmRTZXR0aW5ncygpO1xuXG4gICAgICAgIC8vIFVwZGF0ZSBwb3NpdGlvbiBvZiBhbGwgdGhlIHBsYXllcnMgaW4gdGhlIHNhbWUgd29ybGQuXG4gICAgICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgICAgICAgdGhpcy5nZXRXb3JsZCgpXG4gICAgICAgICAgICAgICAgLmdldFBsYXllcnMoKVxuICAgICAgICAgICAgICAgIC5tYXAoKHRhcmdldCkgPT4gdGhpcy5nZXROZXR3b3JrU2Vzc2lvbigpLmJyb2FkY2FzdE1vdmUodGFyZ2V0LCBNb3ZlbWVudFR5cGUuUmVzZXQpKVxuICAgICAgICApO1xuXG4gICAgICAgIC8vIEZpbmFsbHkgbWFyayB0aGUgcGxheWVyIGFzIGNvbm5lY3RlZC5cbiAgICAgICAgdGhpcy5zZXJ2ZXIuZ2V0TG9nZ2VyKCkuZGVidWcoYChDb21wbGV0ZSBwbGF5ZXIgY3JlYXRpb24gdG9vayAke3RoaXMudGltZXIuc3RvcCgpfSBtcylgKTtcbiAgICAgICAgdGhpcy5jb25uZWN0ZWQgPSB0cnVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE9uIGRpc2FibGUgaG9vay5cbiAgICAgKiBAZ3JvdXAgTGlmZWN5Y2xlXG4gICAgICovXG4gICAgcHVibGljIGFzeW5jIGRpc2FibGUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGlmICh0aGlzLmNvbm5lY3RlZCAmJiB0aGlzLnh1aWQpIGF3YWl0IHRoaXMuZ2V0V29ybGQoKS5zYXZlUGxheWVyRGF0YSh0aGlzKTtcbiAgICAgICAgYXdhaXQgdGhpcy5nZXRXb3JsZCgpLnJlbW92ZUVudGl0eSh0aGlzKTtcblxuICAgICAgICAvLyBEZS1zcGF3biB0aGUgcGxheWVyIHRvIGFsbCBvbmxpbmUgcGxheWVyc1xuICAgICAgICBhd2FpdCB0aGlzLmdldE5ldHdvcmtTZXNzaW9uKCkucmVtb3ZlRnJvbVBsYXllckxpc3QoKTtcbiAgICAgICAgZm9yIChjb25zdCBvbmxpbmVQbGF5ZXIgb2YgdGhpcy5zZXJ2ZXIuZ2V0U2Vzc2lvbk1hbmFnZXIoKS5nZXRBbGxQbGF5ZXJzKCkpIHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuZ2V0TmV0d29ya1Nlc3Npb24oKS5zZW5kRGVzcGF3bihvbmxpbmVQbGF5ZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQW5ub3VuY2UgZGlzY29ubmVjdGlvblxuICAgICAgICBjb25zdCBldmVudCA9IG5ldyBDaGF0RXZlbnQoXG4gICAgICAgICAgICBuZXcgQ2hhdCh7XG4gICAgICAgICAgICAgICAgc2VuZGVyOiB0aGlzLnNlcnZlci5nZXRDb25zb2xlKCkhLFxuICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGDCp2UlbXVsdGlwbGF5ZXIucGxheWVyLmxlZnRgLFxuICAgICAgICAgICAgICAgIHBhcmFtZXRlcnM6IFt0aGlzLmdldE5hbWUoKV0sXG4gICAgICAgICAgICAgICAgbmVlZHNUcmFuc2xhdGlvbjogdHJ1ZSxcbiAgICAgICAgICAgICAgICB0eXBlOiBDaGF0VHlwZS5UUkFOU0xBVElPTlxuICAgICAgICAgICAgfSlcbiAgICAgICAgKTtcbiAgICAgICAgYXdhaXQgdGhpcy5zZXJ2ZXIuZW1pdCgnY2hhdCcsIGV2ZW50KTtcblxuICAgICAgICB0aGlzLmNvbm5lY3RlZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLnNlcnZlci5yZW1vdmVMaXN0ZW5lcignY2hhdCcsIHRoaXMuY2hhdEhhbmRsZXIpO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgY2hhdEhhbmRsZXIoZXZ0OiBDaGF0RXZlbnQpIHtcbiAgICAgICAgaWYgKGV2dC5pc0NhbmNlbGxlZCgpKSByZXR1cm47XG5cbiAgICAgICAgLy8gVE9ETzogcHJvcGVyIGNoYW5uZWwgc3lzdGVtXG4gICAgICAgIGlmIChcbiAgICAgICAgICAgIGV2dC5nZXRDaGF0KCkuZ2V0Q2hhbm5lbCgpID09PSAnKi5ldmVyeW9uZScgfHxcbiAgICAgICAgICAgIChldnQuZ2V0Q2hhdCgpLmdldENoYW5uZWwoKSA9PT0gJyoub3BzJyAmJiB0aGlzLmlzT3AoKSkgfHxcbiAgICAgICAgICAgIGV2dC5nZXRDaGF0KCkuZ2V0Q2hhbm5lbCgpID09PSBgKi5wbGF5ZXIuJHt0aGlzLmdldE5hbWUoKX1gXG4gICAgICAgIClcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuc2VuZE1lc3NhZ2UoXG4gICAgICAgICAgICAgICAgZXZ0LmdldENoYXQoKS5nZXRNZXNzYWdlKCksXG4gICAgICAgICAgICAgICAgZXZ0LmdldENoYXQoKS5nZXRUeXBlKCkgYXMgbnVtYmVyIGFzIFRleHRUeXBlLFxuICAgICAgICAgICAgICAgIGV2dC5nZXRDaGF0KCkuZ2V0UGFyYW1ldGVycygpLFxuICAgICAgICAgICAgICAgIGV2dC5nZXRDaGF0KCkuaXNOZWVkc1RyYW5zbGF0aW9uKClcbiAgICAgICAgICAgICk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVXNlZCB0byBtYXRjaCB2YW5pbGxhIGJlaGF2aW9yLCB3aWxsIHNlbmQgY2h1bmtzXG4gICAgICogd2l0aCBhbiBpbml0aWFsIHZpZXcgcmFkaXVzIG9mIFZBTklMTEFfREVGQVVMVF9TUEFXTl9SQURJVVMuXG4gICAgICovXG4gICAgcHVibGljIGFzeW5jIHNlbmRJbml0aWFsU3Bhd25DaHVua3MoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGNvbnN0IG1pblggPSBDb29yZGluYXRlVXRpbHMuZnJvbUJsb2NrVG9DaHVuayh0aGlzLngpIC0gVkFOSUxMQV9ERUZBVUxUX1NQQVdOX1JBRElVUztcbiAgICAgICAgY29uc3QgbWluWiA9IENvb3JkaW5hdGVVdGlscy5mcm9tQmxvY2tUb0NodW5rKHRoaXMueikgLSBWQU5JTExBX0RFRkFVTFRfU1BBV05fUkFESVVTO1xuICAgICAgICBjb25zdCBtYXhYID0gQ29vcmRpbmF0ZVV0aWxzLmZyb21CbG9ja1RvQ2h1bmsodGhpcy54KSArIFZBTklMTEFfREVGQVVMVF9TUEFXTl9SQURJVVM7XG4gICAgICAgIGNvbnN0IG1heFogPSBDb29yZGluYXRlVXRpbHMuZnJvbUJsb2NrVG9DaHVuayh0aGlzLnopICsgVkFOSUxMQV9ERUZBVUxUX1NQQVdOX1JBRElVUztcblxuICAgICAgICBjb25zdCBzYXZlZENodW5rczogQ2h1bmtDb29yZFtdID0gW107XG4gICAgICAgIGNvbnN0IHNlbmRRdWV1ZTogQXJyYXk8UHJvbWlzZTxDaHVuaz4+ID0gW107XG4gICAgICAgIGZvciAobGV0IGNodW5rWCA9IG1pblg7IGNodW5rWCA8PSBtYXhYOyArK2NodW5rWCkge1xuICAgICAgICAgICAgZm9yIChsZXQgY2h1bmtaID0gbWluWjsgY2h1bmtaIDw9IG1heFo7ICsrY2h1bmtaKSB7XG4gICAgICAgICAgICAgICAgLy8gVE9ETzogdmFuaWxsYSBkb2VzIG5vdCBzZW5kIGFsbCBvZiB0aGVtLCBidXQgaW4gYSByYW5nZVxuICAgICAgICAgICAgICAgIC8vIGZvciBleGFtcGxlIGl0IGRvZXMgc2VuZCB0aGVtIGZyb20geCA9PiBbLTM7IDNdIGFuZCB6ID0+IFstMzsgMl1cbiAgICAgICAgICAgICAgICBzYXZlZENodW5rcy5wdXNoKHsgeDogY2h1bmtYLCB6OiBjaHVua1ogfSk7XG4gICAgICAgICAgICAgICAgc2VuZFF1ZXVlLnB1c2godGhpcy5nZXRXb3JsZCgpLmdldENodW5rKGNodW5rWCwgY2h1bmtaKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBhd2FpdCB0aGlzLm5ldHdvcmtTZXNzaW9uLnNlbmROZXR3b3JrQ2h1bmtQdWJsaXNoZXIoVkFOSUxMQV9ERUZBVUxUX1NQQVdOX1JBRElVUywgc2F2ZWRDaHVua3MpO1xuXG4gICAgICAgIGNvbnN0IGdldFVuaXF1ZUNodW5rcyA9IChzZW5kTGlzdDogQ2h1bmtDb29yZFtdKSA9PiB7XG4gICAgICAgICAgICBjb25zdCB4U2V0ID0gbmV3IFNldDxudW1iZXI+KCk7XG4gICAgICAgICAgICBjb25zdCB6U2V0ID0gbmV3IFNldDxudW1iZXI+KCk7XG5cbiAgICAgICAgICAgIGZvciAoY29uc3QgY29vcmQgb2Ygc2VuZExpc3QpIHtcbiAgICAgICAgICAgICAgICB4U2V0LmFkZChjb29yZC54KTtcbiAgICAgICAgICAgICAgICB6U2V0LmFkZChjb29yZC56KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIE1hdGguZmxvb3IoKHhTZXQuc2l6ZSArIHpTZXQuc2l6ZSkgLyAyKTtcbiAgICAgICAgfTtcblxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGdldFVuaXF1ZUNodW5rcyhzYXZlZENodW5rcyk7ICsraSkge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5uZXR3b3JrU2Vzc2lvbi5zZW5kTmV0d29ya0NodW5rUHVibGlzaGVyKFZBTklMTEFfREVGQVVMVF9TUEFXTl9SQURJVVMsIFtdKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvciBhd2FpdCAoY29uc3QgY2h1bmsgb2Ygc2VuZFF1ZXVlKSB7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLm5ldHdvcmtTZXNzaW9uLnNlbmRDaHVuayhjaHVuayk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGFuZ2UgdGhlIHBsYXllcidzIGN1cnJlbnQgd29ybGQuXG4gICAgICogQHBhcmFtIHtXb3JsZH0gd29ybGQgLSB0aGUgbmV3IHdvcmxkXG4gICAgICovXG4gICAgcHVibGljIGFzeW5jIHNldFdvcmxkKHdvcmxkOiBXb3JsZCkge1xuICAgICAgICBjb25zdCBkaW0wID0gbmV3IENoYW5nZURpbWVuc2lvblBhY2tldCgpO1xuICAgICAgICBkaW0wLmRpbWVuc2lvbiA9IDA7XG4gICAgICAgIGRpbTAucG9zaXRpb24gPSB0aGlzLmdldFBvc2l0aW9uKCk7XG4gICAgICAgIGRpbTAucmVzcGF3biA9IGZhbHNlO1xuXG4gICAgICAgIGNvbnN0IGRpbTEgPSBuZXcgQ2hhbmdlRGltZW5zaW9uUGFja2V0KCk7XG4gICAgICAgIGRpbTEuZGltZW5zaW9uID0gMTtcbiAgICAgICAgZGltMS5wb3NpdGlvbiA9IHRoaXMuZ2V0UG9zaXRpb24oKTtcbiAgICAgICAgZGltMS5yZXNwYXduID0gZmFsc2U7XG5cbiAgICAgICAgYXdhaXQgdGhpcy5zZW5kRGVzcGF3bigpO1xuICAgICAgICBhd2FpdCB0aGlzLmdldFdvcmxkKCkucmVtb3ZlRW50aXR5KHRoaXMpO1xuXG4gICAgICAgIGF3YWl0IHN1cGVyLnNldFdvcmxkKHdvcmxkKTtcbiAgICAgICAgYXdhaXQgd29ybGQuYWRkRW50aXR5KHRoaXMpO1xuXG4gICAgICAgIGF3YWl0IHRoaXMubmV0d29ya1Nlc3Npb24uc2VuZChkaW0wKTtcbiAgICAgICAgYXdhaXQgdGhpcy5uZXR3b3JrU2Vzc2lvbi5zZW5kUGxheVN0YXR1cyhQbGF5U3RhdHVzVHlwZS5QbGF5ZXJTcGF3bik7XG4gICAgICAgIGF3YWl0IHRoaXMubmV0d29ya1Nlc3Npb24uc2VuZChkaW0xKTtcbiAgICAgICAgYXdhaXQgdGhpcy5uZXR3b3JrU2Vzc2lvbi5zZW5kUGxheVN0YXR1cyhQbGF5U3RhdHVzVHlwZS5QbGF5ZXJTcGF3bik7XG5cbiAgICAgICAgYXdhaXQgdGhpcy5zZW5kSW5pdGlhbFNwYXduQ2h1bmtzKCk7XG5cbiAgICAgICAgYXdhaXQgdGhpcy5uZXR3b3JrU2Vzc2lvbi5zZW5kKGRpbTEpO1xuICAgICAgICBhd2FpdCB0aGlzLm5ldHdvcmtTZXNzaW9uLnNlbmRQbGF5U3RhdHVzKFBsYXlTdGF0dXNUeXBlLlBsYXllclNwYXduKTtcbiAgICAgICAgYXdhaXQgdGhpcy5uZXR3b3JrU2Vzc2lvbi5zZW5kKGRpbTApO1xuICAgICAgICBhd2FpdCB0aGlzLm5ldHdvcmtTZXNzaW9uLnNlbmRQbGF5U3RhdHVzKFBsYXlTdGF0dXNUeXBlLlBsYXllclNwYXduKTtcblxuICAgICAgICBhd2FpdCB0aGlzLm5ldHdvcmtTZXNzaW9uLmNsZWFyQ2h1bmtzKCk7XG4gICAgICAgIGF3YWl0IHRoaXMubmV0d29ya1Nlc3Npb24ubmVlZE5ld0NodW5rcygpO1xuICAgICAgICBhd2FpdCB0aGlzLm5ldHdvcmtTZXNzaW9uLnNlbmRQbGF5U3RhdHVzKFBsYXlTdGF0dXNUeXBlLlBsYXllclNwYXduKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgaXNPbmxpbmUoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvbm5lY3RlZDtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgdXBkYXRlKHRpY2s6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBhd2FpdCBzdXBlci51cGRhdGUodGljayk7XG4gICAgICAgIGF3YWl0IHRoaXMubmV0d29ya1Nlc3Npb24udXBkYXRlKHRpY2spO1xuXG4gICAgICAgIC8vIFRPRE86IGdldCBkb2N1bWVudGF0aW9uIGFib3V0IHRpbWluZ3MgZnJvbSB2YW5pbGxhXG4gICAgICAgIC8vIDEgc2Vjb25kIC8gMjAgPSAxIHRpY2ssIDIwICogNSA9IDEgc2Vjb25kXG4gICAgICAgIC8vIDEgc2Vjb25kICogNjAgPSAxIG1pbnV0ZVxuICAgICAgICBpZiAodGljayAlICgyMCAqIDUgKiA2MCAqIDEpID09PSAwKSB7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLm5ldHdvcmtTZXNzaW9uLnNlbmRUaW1lKHRpY2spO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9yIChjb25zdCBjaHVuayBvZiB0aGlzLmNodW5rU2VuZFF1ZXVlKSB7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLm5ldHdvcmtTZXNzaW9uLnNlbmROZXR3b3JrQ2h1bmtQdWJsaXNoZXIodGhpcy52aWV3RGlzdGFuY2UgfHwgVkFOSUxMQV9ERUZBVUxUX1NQQVdOX1JBRElVUywgW10pO1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5uZXR3b3JrU2Vzc2lvbi5zZW5kQ2h1bmsoY2h1bmspO1xuICAgICAgICAgICAgdGhpcy5jaHVua1NlbmRRdWV1ZS5kZWxldGUoY2h1bmspO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIGtpY2socmVhc29uID0gJ3Vua25vd24gcmVhc29uJyk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBhd2FpdCB0aGlzLmRpc2FibGUoKTtcbiAgICAgICAgYXdhaXQgdGhpcy5uZXR3b3JrU2Vzc2lvbi5raWNrKHJlYXNvbik7XG4gICAgICAgIHRoaXMuc2VydmVyLmdldExvZ2dlcigpLnZlcmJvc2UoYFBsYXllciB3aXRoIGlkIMKnYiR7dGhpcy5nZXRSdW50aW1lSWQoKX3Cp3Igd2FzIGtpY2tlZDogJHtyZWFzb259YCk7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIHNlbmRTZXR0aW5ncygpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgYXdhaXQgdGhpcy5nZXROZXR3b3JrU2Vzc2lvbigpLnNlbmRHYW1lbW9kZSgpO1xuXG4gICAgICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgICAgICAgdGhpcy5zZXJ2ZXJcbiAgICAgICAgICAgICAgICAuZ2V0U2Vzc2lvbk1hbmFnZXIoKVxuICAgICAgICAgICAgICAgIC5nZXRBbGxQbGF5ZXJzKClcbiAgICAgICAgICAgICAgICAubWFwKGFzeW5jICh0YXJnZXQpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGFyZ2V0LmdldE5ldHdvcmtTZXNzaW9uKCkuc2VuZEFiaWxpdGllcyh0aGlzKTtcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGFyZ2V0LmdldE5ldHdvcmtTZXNzaW9uKCkuc2VuZFNldHRpbmdzKHRoaXMpO1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGxheWVyIHNwYXduaW5nIGxvZ2ljLlxuICAgICAqL1xuICAgIHB1YmxpYyBhc3luYyBzZW5kU3Bhd24oKSB7XG4gICAgICAgIGF3YWl0IHRoaXMuc2VuZFBvc2l0aW9uKCk7XG4gICAgICAgIGF3YWl0IHRoaXMuc2V0R2FtZW1vZGUoKTtcbiAgICAgICAgYXdhaXQgdGhpcy5nZXROZXR3b3JrU2Vzc2lvbigpLnNlbmRJbnZlbnRvcnkoKTtcbiAgICAgICAgYXdhaXQgdGhpcy5zZW5kU2V0dGluZ3MoKTtcbiAgICB9XG4gICAgcHVibGljIGFzeW5jIHNlbmREZXNwYXduKCkge31cblxuICAgIC8qKlxuICAgICAqIFNlbmQgYSBjaGF0IG1lc3NhZ2UgdG8gdGhlIGNsaWVudC5cbiAgICAgKiBAcGFyYW0gbWVzc2FnZSAtIHRoZSBtZXNzYWdlXG4gICAgICovXG4gICAgcHVibGljIGFzeW5jIHNlbmRNZXNzYWdlKFxuICAgICAgICBtZXNzYWdlOiBzdHJpbmcsXG4gICAgICAgIHR5cGU6IFRleHRUeXBlID0gVGV4dFR5cGUuUmF3LFxuICAgICAgICBwYXJhbWV0ZXJzOiBzdHJpbmdbXSA9IFtdLFxuICAgICAgICBuZWVkc1RyYW5zbGF0aW9uID0gZmFsc2VcbiAgICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgLy8gVE9ETzogRG8gdGhpcyBwcm9wZXJseSBsaWtlIGphdmEgZWRpdGlvbixcbiAgICAgICAgLy8gaW4gb3RoZXIgd29yZHMsIHRoZSBtZXNzYWdlIHNob3VsZCBiZSBKU09OIGZvcm1hdHRlZC5cbiAgICAgICAgYXdhaXQgdGhpcy5uZXR3b3JrU2Vzc2lvbi5zZW5kTWVzc2FnZSh7XG4gICAgICAgICAgICBtZXNzYWdlLFxuICAgICAgICAgICAgcGFyYW1ldGVycyxcbiAgICAgICAgICAgIG5lZWRzVHJhbnNsYXRpb24sXG4gICAgICAgICAgICB0eXBlXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBzZXRHYW1lbW9kZShtb2RlPzogR2FtZXR5cGUpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgbW9kZSA/Pz0gdGhpcy5nYW1lbW9kZTtcblxuICAgICAgICBjb25zdCBldmVudCA9IG5ldyBQbGF5ZXJTZXRHYW1lbW9kZUV2ZW50KHRoaXMsIG1vZGUpO1xuICAgICAgICB0aGlzLnNlcnZlci5wb3N0KFsncGxheWVyU2V0R2FtZW1vZGUnLCBldmVudF0pO1xuICAgICAgICBpZiAoZXZlbnQuaXNDYW5jZWxsZWQoKSkgcmV0dXJuO1xuXG4gICAgICAgIHRoaXMuZ2FtZW1vZGUgPSBldmVudC5nZXRHYW1lbW9kZSgpO1xuICAgICAgICBhd2FpdCB0aGlzLm5ldHdvcmtTZXNzaW9uLnNlbmRHYW1lbW9kZSgpO1xuXG4gICAgICAgIGlmICh0aGlzLmdhbWVtb2RlID09PSBHYW1ldHlwZS5DUkVBVElWRSB8fCB0aGlzLmdhbWVtb2RlID09PSBHYW1ldHlwZS5TUEVDVEFUT1IpIHtcbiAgICAgICAgICAgIHRoaXMubWV0YWRhdGEuc2V0Q2FuRmx5KHRydWUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5tZXRhZGF0YS5zZXRDYW5GbHkoZmFsc2UpO1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5zZXRGbHlpbmcoZmFsc2UpO1xuICAgICAgICB9XG5cbiAgICAgICAgYXdhaXQgdGhpcy5zZW5kU2V0dGluZ3MoKTtcbiAgICAgICAgYXdhaXQgdGhpcy5uZXR3b3JrU2Vzc2lvbi5zZW5kR2FtZW1vZGUoKTtcbiAgICAgICAgYXdhaXQgdGhpcy5uZXR3b3JrU2Vzc2lvbi5zZW5kTWV0YWRhdGEoKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0TmV0d29ya1Nlc3Npb24oKTogUGxheWVyU2Vzc2lvbiB7XG4gICAgICAgIHJldHVybiB0aGlzLm5ldHdvcmtTZXNzaW9uO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXRBZGRyZXNzKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5hZGRyZXNzO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXROYW1lKCk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiB0aGlzLm1ldGFkYXRhLm5hbWVUYWc7XG4gICAgfVxuXG4gICAgcHVibGljIGdldEZvcm1hdHRlZFVzZXJuYW1lKCk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiBgPCR7dGhpcy5nZXROYW1lKCl9PmA7XG4gICAgfVxuXG4gICAgcHVibGljIGdldFBlcm1pc3Npb25zKCk6IHN0cmluZ1tdIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucGVybWlzc2lvbnM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IHRoZSBYVUlEIG9mIHRoZSBwbGF5ZXIuXG4gICAgICogQHJldHVybnMge3N0cmluZyB8IG51bGx9IFhVSUQgb2YgdGhlIHBsYXllciBvciBudWxsIGlmIG5vdCBhdmFpbGFibGVcbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0WFVJRCgpOiBzdHJpbmcgfCBudWxsIHtcbiAgICAgICAgcmV0dXJuIHRoaXMueHVpZCB8fCBudWxsO1xuICAgIH1cblxuICAgIHB1YmxpYyBpc1BsYXllcigpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2sgaWYgdGhlIGBQbGF5ZXJgIGlzIGFuIG9wZXJhdG9yLlxuICAgICAqIEByZXR1cm5zIGB0cnVlYCBpZiB0aGlzIHBsYXllciBpcyBhbiBvcGVyYXRvciBvdGhlcndpc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBwdWJsaWMgaXNPcCgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2VydmVyLmdldFBlcm1pc3Npb25NYW5hZ2VyKCkuaXNPcCh0aGlzLmdldE5hbWUoKSk7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIHNldFNwcmludGluZyhzcHJpbnRpbmc6IGJvb2xlYW4pIHtcbiAgICAgICAgaWYgKHNwcmludGluZyA9PT0gdGhpcy5tZXRhZGF0YS5zcHJpbnRpbmcpIHJldHVybjtcblxuICAgICAgICBjb25zdCBldmVudCA9IG5ldyBQbGF5ZXJUb2dnbGVTcHJpbnRFdmVudCh0aGlzLCBzcHJpbnRpbmcpO1xuICAgICAgICB0aGlzLnNlcnZlci5wb3N0KFsncGxheWVyVG9nZ2xlU3ByaW50JywgZXZlbnRdKTtcbiAgICAgICAgaWYgKGV2ZW50LmlzQ2FuY2VsbGVkKCkpIHJldHVybjtcblxuICAgICAgICB0aGlzLm1ldGFkYXRhLnNldFNwcmludGluZyhldmVudC5nZXRJc1NwcmludGluZygpKTtcbiAgICAgICAgYXdhaXQgdGhpcy5uZXR3b3JrU2Vzc2lvbi5zZW5kTWV0YWRhdGEoKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgaXNGbHlpbmcoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmZseWluZztcbiAgICB9XG4gICAgcHVibGljIGFzeW5jIHNldEZseWluZyhmbHlpbmc6IGJvb2xlYW4pIHtcbiAgICAgICAgaWYgKGZseWluZyA9PT0gdGhpcy5pc0ZseWluZygpKSByZXR1cm47XG5cbiAgICAgICAgaWYgKCF0aGlzLm1ldGFkYXRhLmNhbkZseSkge1xuICAgICAgICAgICAgdGhpcy5mbHlpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuc2VuZFNldHRpbmdzKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBldmVudCA9IG5ldyBQbGF5ZXJUb2dnbGVGbGlnaHRFdmVudCh0aGlzLCBmbHlpbmcpO1xuICAgICAgICB0aGlzLnNlcnZlci5wb3N0KFsncGxheWVyVG9nZ2xlRmxpZ2h0JywgZXZlbnRdKTtcbiAgICAgICAgaWYgKGV2ZW50LmlzQ2FuY2VsbGVkKCkpIHJldHVybjtcblxuICAgICAgICB0aGlzLmZseWluZyA9IGV2ZW50LmdldElzRmx5aW5nKCk7XG4gICAgICAgIGF3YWl0IHRoaXMuc2VuZFNldHRpbmdzKCk7XG4gICAgfVxuXG4gICAgcHVibGljIGlzU25lYWtpbmcoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnNuZWFraW5nO1xuICAgIH1cbiAgICBwdWJsaWMgYXN5bmMgc2V0U25lYWtpbmcodmFsOiBib29sZWFuKSB7XG4gICAgICAgIGlmICh2YWwgPT09IHRoaXMuc25lYWtpbmcpIHJldHVybjtcbiAgICAgICAgdGhpcy5zbmVha2luZyA9IHZhbDtcbiAgICB9XG5cbiAgICBwdWJsaWMgaXNPbkdyb3VuZCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMub25Hcm91bmQ7XG4gICAgfVxuICAgIHB1YmxpYyBhc3luYyBzZXRPbkdyb3VuZCh2YWw6IGJvb2xlYW4pIHtcbiAgICAgICAgaWYgKHZhbCA9PT0gdGhpcy5vbkdyb3VuZCkgcmV0dXJuO1xuICAgICAgICB0aGlzLm9uR3JvdW5kID0gdmFsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldCB0aGUgcG9zaXRpb24uXG4gICAgICogQHBhcmFtIHtvYmplY3R9IG9wdGlvbnMgLSBUaGUgb3B0aW9ucyB0byBzZXQgdGhlIHBvc2l0aW9uLlxuICAgICAqIEBwYXJhbSB7VmVjdG9yM30gb3B0aW9ucy5wb3NpdGlvbiAtIFRoZSBuZXcgcG9zaXRpb24uXG4gICAgICogQHBhcmFtIHtNb3ZlbWVudFR5cGV9IFtvcHRpb25zLnR5cGU9TW92ZW1lbnRUeXBlLk5vcm1hbF0gLSBUaGUgbW92ZW1lbnQgdHlwZS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW29wdGlvbnMucGl0Y2g9dGhpcy5waXRjaF0gLSBUaGUgbmV3IHBpdGNoLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbb3B0aW9ucy55YXc9dGhpcy55YXddIC0gVGhlIG5ldyB5YXcuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtvcHRpb25zLmhlYWRZYXc9dGhpcy5oZWFkWWF3XSAtIFRoZSBuZXcgaGVhZCB5YXcuXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbYnJvYWRjYXN0PXRydWVdIC0gV2hldGhlciB0byBicm9hZGNhc3QgdGhlIHBvc2l0aW9uIGNoYW5nZS5cbiAgICAgKiBAcmVtYXJrcyBUaGlzIHdpbGwgbm90aWZ5IHRoZSBwbGF5ZXIncyBjbGllbnQgYWJvdXQgdGhlIHBvc2l0aW9uIGNoYW5nZS5cbiAgICAgKi9cbiAgICBwdWJsaWMgYXN5bmMgc2V0UG9zaXRpb24oXG4gICAgICAgIHtcbiAgICAgICAgICAgIHBvc2l0aW9uLFxuICAgICAgICAgICAgdHlwZSA9IE1vdmVtZW50VHlwZS5Ob3JtYWwsXG4gICAgICAgICAgICBwaXRjaCA9IHRoaXMucGl0Y2gsXG4gICAgICAgICAgICB5YXcgPSB0aGlzLnlhdyxcbiAgICAgICAgICAgIGhlYWRZYXcgPSB0aGlzLmhlYWRZYXdcbiAgICAgICAgfToge1xuICAgICAgICAgICAgcG9zaXRpb246IFZlY3RvcjM7XG4gICAgICAgICAgICB0eXBlPzogTW92ZW1lbnRUeXBlO1xuICAgICAgICAgICAgcGl0Y2g/OiBudW1iZXI7XG4gICAgICAgICAgICB5YXc/OiBudW1iZXI7XG4gICAgICAgICAgICBoZWFkWWF3PzogbnVtYmVyO1xuICAgICAgICB9LFxuICAgICAgICBicm9hZGNhc3QgPSB0cnVlXG4gICAgKSB7XG4gICAgICAgIGF3YWl0IHN1cGVyLnNldFBvc2l0aW9uKHsgcG9zaXRpb24gfSk7XG4gICAgICAgIHRoaXMucGl0Y2ggPSBwaXRjaDtcbiAgICAgICAgdGhpcy55YXcgPSB5YXc7XG4gICAgICAgIHRoaXMuaGVhZFlhdyA9IGhlYWRZYXc7XG5cbiAgICAgICAgaWYgKCFicm9hZGNhc3QpIHJldHVybjtcbiAgICAgICAgYXdhaXQgdGhpcy5uZXR3b3JrU2Vzc2lvbi5icm9hZGNhc3RNb3ZlKHRoaXMsIHR5cGUpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBTZW5kIHRoZSBwb3NpdGlvbiB0byBhbGwgdGhlIHBsYXllcnMgaW4gdGhlIHNhbWUgd29ybGQuXG4gICAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gdGhlIHBvc2l0aW9uIGlzIHNlbnQuXG4gICAgICovXG4gICAgcHVibGljIGFzeW5jIHNlbmRQb3NpdGlvbigpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgYXdhaXQgc3VwZXIuc2VuZFBvc2l0aW9uKCk7XG4gICAgfVxufVxuIl0sIm5hbWVzIjpbIkh1bWFuIiwiR2FtZXR5cGUiLCJUaW1lciIsIlBsYXllclNlc3Npb24iLCJnZXRHYW1ldHlwZUlkIiwiVmVjdG9yMyIsIk1vdmVtZW50VHlwZSIsIkNoYXRFdmVudCIsIkNoYXQiLCJDaGF0VHlwZSIsIkNvb3JkaW5hdGVVdGlscyIsIkNoYW5nZURpbWVuc2lvblBhY2tldCIsIlBsYXlTdGF0dXNUeXBlIiwiVGV4dFR5cGUiLCJQbGF5ZXJTZXRHYW1lbW9kZUV2ZW50IiwiUGxheWVyVG9nZ2xlU3ByaW50RXZlbnQiLCJQbGF5ZXJUb2dnbGVGbGlnaHRFdmVudCJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBMkJPLE1BQU0sNEJBQStCLEdBQUE7QUFFNUMsTUFBcUIsZUFBZUEsb0JBQU0sQ0FBQTtBQUFBLEVBQ3JCLE9BQUE7QUFBQSxFQUNBLGNBQUE7QUFBQSxFQUNULFdBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQUtBLEtBQUE7QUFBQSxFQUNBLFNBQVksR0FBQSxLQUFBO0FBQUEsRUFFYixJQUFPLEdBQUEsRUFBQTtBQUFBLEVBQ1AsUUFBVyxHQUFBLENBQUE7QUFBQSxFQUVYLE1BQVMsR0FBQSxFQUFBO0FBQUEsRUFDVCxJQUFvQixHQUFBLElBQUE7QUFBQSxFQUVwQixZQUFlLEdBQUEsQ0FBQTtBQUFBLEVBQ2YsV0FBcUJDLGtCQUFTLENBQUEsYUFBQTtBQUFBLEVBRTdCLFFBQVcsR0FBQSxLQUFBO0FBQUEsRUFDWCxNQUFTLEdBQUEsS0FBQTtBQUFBLEVBQ1QsUUFBVyxHQUFBLEtBQUE7QUFBQSxFQUVaLGNBQWlCLEdBQUEsRUFBQTtBQUFBO0FBQUEsRUFDakIsTUFBd0IsR0FBQSxJQUFBO0FBQUEsRUFFZixjQUFBLHVCQUFxQixHQUFXLEVBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQUt6QyxXQUFZLENBQUE7QUFBQSxJQUNmLFVBQUE7QUFBQSxJQUNBLEtBQUE7QUFB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