sdk7-npc-utils
Version:
A collection of helpers to make it easier to build a Decentraland scene using the SDK 7.
366 lines • 55.6 kB
JavaScript
import { Animator, AvatarShape, Billboard, engine, GltfContainer, MeshCollider, MeshRenderer, pointerEventsSystem, Transform } from '@dcl/sdk/ecs';
import { Color3, Vector3 } from '@dcl/sdk/math';
import { NPCPathType, NPCState, NPCType } from './types';
import * as utils from '@dcl-sdk/utils';
import { IsFollowingPath } from './components';
import { handleDialogTyping, handlePathTimes } from './systems';
import { createDialog } from './ui';
import { addDialog, closeDialog, npcDialogComponent } from './dialog';
export const walkingTimers = new Map();
export const npcDataComponent = new Map();
export let activeNPC = 0;
const walkingSystem = engine.addSystem(handlePathTimes);
const dialogSystem = engine.addSystem(handleDialogTyping);
const isCooldown = new Map();
const onActivateCbs = new Map();
const onWalkAwayCbs = new Map();
const animTimers = new Map();
const pointReachedCallbacks = new Map();
const onFinishCallbacks = new Map();
export function showDebug(debug) {
utils.triggers.enableDebugDraw(debug);
}
export function getData(npc) {
return npcDataComponent.get(npc);
}
export function create(transform, data) {
let npc = engine.addEntity();
Transform.create(npc, transform);
npcDataComponent.set(npc, {
introduced: false,
inCooldown: false,
coolDownDuration: data && data.coolDownDuration ? data.coolDownDuration : 5,
faceUser: data.faceUser,
walkingSpeed: 2,
walkingAnim: data && data.walkingAnim ? data.walkingAnim : undefined,
bubbleHeight: 2,
pathData: data.pathData ? data.pathData : undefined,
currentPathData: [],
manualStop: false,
pathIndex: 0,
state: NPCState.STANDING
});
if (data && data.noUI) { }
else if (data && data.portrait) { }
else {
addDialog(npc, data && data.dialogSound ? data.dialogSound : undefined);
createDialog(npc);
}
onActivateCbs.set(npc, () => {
data.onActivate();
});
if (data && data.onWalkAway) {
onWalkAwayCbs.set(npc, () => {
if (!data || !data.continueOnWalkAway) {
if (npcDialogComponent.has(npc)) {
npcDialogComponent.get(npc).visible = false;
}
}
else {
if (npcDialogComponent.has(npc)) {
npcDialogComponent.get(npc).visible = false;
}
}
data.onWalkAway();
});
}
addNPCBones(npc, data);
addClickReactions(npc, data);
addTriggerArea(npc, data);
if (data && data.pathData && data.pathData.speed) {
let npcData = npcDataComponent.get(npc);
npcData.walkingSpeed = data.pathData.speed;
}
if (data && data.coolDownDuration) {
let npcData = npcDataComponent.get(npc);
npcData.coolDownDuration = data.coolDownDuration;
}
if (data && data.pathData) {
let npcData = npcDataComponent.get(npc);
followPath(npc, npcData.pathData);
}
return npc;
}
function addNPCBones(npc, data) {
switch (data.type) {
case NPCType.AVATAR:
AvatarShape.create(npc, {
id: "npc",
name: "NPC",
bodyShape: "urn:decentraland:off-chain:base-avatars:BaseMale",
emotes: [],
wearables: [
"urn:decentraland:off-chain:base-avatars:f_eyes_00",
"urn:decentraland:off-chain:base-avatars:f_eyebrows_00",
"urn:decentraland:off-chain:base-avatars:f_mouth_00",
"urn:decentraland:off-chain:base-avatars:comfy_sport_sandals",
"urn:decentraland:off-chain:base-avatars:soccer_pants",
"urn:decentraland:off-chain:base-avatars:elegant_sweater",
],
});
break;
case NPCType.CUSTOM:
GltfContainer.create(npc, {
src: data && data.model ? data.model : ""
});
Animator.create(npc, {
states: [{
name: data && data.idleAnim ? data.idleAnim : 'Idle',
clip: data && data.idleAnim ? data.idleAnim : 'Idle',
loop: true
}]
});
npcDataComponent.get(npc).idleAnim = data && data.idleAnim ? data.idleAnim : 'Idle';
Animator.playSingleAnimation(npc, npcDataComponent.get(npc).idleAnim);
let npcData = npcDataComponent.get(npc);
npcData.lastPlayedAnim = npcDataComponent.get(npc).idleAnim;
if (data && data.walkingAnim) {
npcDataComponent.get(npc).walkingAnim = data.walkingAnim;
let animations = Animator.getMutable(npc);
animations.states.push({ name: data.walkingAnim, clip: data.walkingAnim, loop: true });
}
break;
case NPCType.BLANK:
MeshRenderer.setBox(npc);
MeshCollider.setBox(npc);
break;
}
}
function addClickReactions(npc, data) {
let activateButton = data && data.onlyClickTrigger ? 0 : 1;
pointerEventsSystem.onPointerDown(npc, function () {
if (isCooldown.has(npc) || (npcDialogComponent.get(npc).visible))
return;
console.log("clicked entity");
activate(npc);
}, {
button: activateButton,
hoverText: data && data.hoverText ? data.hoverText : 'Talk',
showFeedback: data && data.onlyExternalTrigger ? false : true,
});
if (data && data.onlyExternalTrigger) {
console.log("only external trigger, removed pointer");
pointerEventsSystem.removeOnPointerDown(npc);
}
}
function addTriggerArea(npc, data) {
let triggerData = {};
if (!data || (data && !data.onlyExternalTrigger && !data.onlyClickTrigger && !data.onlyETrigger)) {
onActivateCbs.set(npc, () => {
if (isCooldown.has(npc)) {
console.log(npc, ' in cooldown');
return;
}
else if ((npcDialogComponent.has(npc) && npcDialogComponent.get(npc).visible) ||
(data && data.onlyExternalTrigger) ||
(data && data.onlyClickTrigger)) {
return;
}
data.onActivate();
});
triggerData.onCameraEnter = onActivateCbs.get(npc);
}
if (!data || (data && !data.continueOnWalkAway)) {
triggerData.onCameraExit = () => {
handleWalkAway(npc);
};
}
if (!data ||
(data && !data.onlyExternalTrigger && !data.onlyClickTrigger && !data.onlyETrigger)) {
triggerData.onCameraEnter = () => {
if (isCooldown.has(npc)) {
console.log(npc, ' in cooldown');
return;
}
activate(npc);
};
}
if (triggerData.onCameraEnter || triggerData.onCameraExit) {
utils.triggers.addTrigger(npc, 254, 1, [{ type: 'sphere', position: Vector3.Zero(), radius: data.reactDistance != undefined ? data.reactDistance : 6 }], triggerData.onCameraEnter ? triggerData.onCameraEnter : undefined, triggerData.onCameraExit ? triggerData.onCameraExit : undefined, Color3.Red());
}
}
export function followPath(npc, data) {
let npcData = npcDataComponent.get(npc);
let path = [];
if (data) {
npcData.pathData = data;
if (npcData.faceUser) {
Billboard.deleteFrom(npc);
}
if (data.startingPoint) {
data.path?.splice(0, data.startingPoint - 1);
}
let pos = Transform.get(npc).position;
path.push(Vector3.create(pos.x, pos.y, pos.z));
data.path?.forEach((p) => {
path.push(p);
});
onFinishCallbacks.set(npc, () => {
console.log('on finished callback');
if (data && data.onFinishCallback && !data.loop) {
data.onFinishCallback;
}
stopPath(npc);
});
pointReachedCallbacks.set(npc, () => {
console.log('on point reached callback');
let data = npcDataComponent.get(npc);
data.pathIndex += 1;
data.onReachedPointCallback ? data.onReachedPointCallback : undefined;
});
walkNPC(npc, npcData, data.pathType, data.totalDuration, path, pointReachedCallbacks.get(npc), onFinishCallbacks.get(npc));
}
else {
if (npcData.manualStop) {
console.log('we have manual stop, need to pick back up where we left off');
}
else {
console.log('we are trying to follow a path witout starting one prior');
}
}
}
function walkNPC(npc, npcData, type, duration, path, pointReachedCallback, finishedCallback) {
if (IsFollowingPath.has(npc)) {
IsFollowingPath.deleteFrom(npc);
walkingTimers.delete(npc);
}
IsFollowingPath.create(npc);
if (type) {
if (type == NPCPathType.RIGID_PATH) {
utils.paths.startStraightPath(npc, path, duration, true, () => { finishedCallback(); }, () => { pointReachedCallback(); });
}
else {
utils.paths.startSmoothPath(npc, path, duration, 30, true, () => { finishedCallback(); }, () => { pointReachedCallback(); });
}
}
else {
utils.paths.startSmoothPath(npc, path, duration, 20, true, () => { finishedCallback(); }, () => { pointReachedCallback(); });
}
if (npcData.walkingAnim) {
Animator.playSingleAnimation(npc, npcDataComponent.get(npc).walkingAnim, true);
npcData.lastPlayedAnim = npcDataComponent.get(npc).walkingAnim;
}
npcData.state = NPCState.FOLLOWPATH;
console.log('debug here');
}
export function stopWalking(npc, duration, finished) {
let npcData = npcDataComponent.get(npc);
npcData.state = NPCState.STANDING;
npcData.manualStop = true;
stopPath(npc);
if (duration) {
utils.timers.setTimeout(() => {
if (npcData.path) {
Animator.stopAllAnimations(npc, true);
if (npcDataComponent.get(npc).walkingAnim) {
Animator.playSingleAnimation(npc, npcDataComponent.get(npc).walkingAnim, true);
npcData.lastPlayedAnim = npcDataComponent.get(npc).walkingAnim;
}
let duration = npcData.pathData.totalDuration;
let currentTimer = walkingTimers.get(npc);
console.log('current time is', currentTimer);
if (currentTimer) {
duration -= currentTimer;
}
let path = [];
npcData.pathData.path.forEach((p) => {
path.push(p);
});
path.splice(0, npcData.pathIndex);
let pos = Transform.get(npc).position;
path.unshift(Vector3.create(pos.x, pos.y, pos.z));
npcData.manualStop = false;
walkNPC(npc, npcData, npcData.pathData.pathType, duration, path, pointReachedCallbacks.get(npc), onFinishCallbacks.get(npc));
}
}, duration * 1000);
}
}
function stopPath(npc) {
utils.paths.stopPath(npc);
IsFollowingPath.deleteFrom(npc);
let npcData = npcDataComponent.get(npc);
if (npcData.walkingAnim) {
Animator.playSingleAnimation(npc, npcDataComponent.get(npc).walkingAnim);
npcData.lastPlayedAnim = npcData.idleAnim;
}
if (!npcData.manualStop) {
if (npcData.pathData.loop) {
npcData.pathIndex = 0;
walkingTimers.delete(npc);
console.log('we are looping path', npcData);
followPath(npc, npcData.pathData);
console.log(npcData);
}
}
}
export function activate(npc) {
activeNPC = npc;
onActivateCbs.get(npc)();
let npcData = npcDataComponent.get(npc);
if (npcData.faceUser) {
Billboard.create(npc, {
billboardMode: 2
});
}
isCooldown.set(npc, true);
npcData.inCooldown = true;
utils.timers.setTimeout(function () {
isCooldown.delete(npc);
npcDataComponent.get(npc).inCooldown = false;
if (Billboard.has(npc)) {
Billboard.deleteFrom(npc);
}
}, 1000 * npcData.coolDownDuration);
console.log('activated npc,', npcDataComponent.get(npc));
}
function endInteraction(npc) {
let npcData = npcDataComponent.get(npc);
npcData.state = NPCState.STANDING;
if (npcDialogComponent.has(npc) && npcDialogComponent.get(npc).visible) {
closeDialog(npc);
}
if (Billboard.has(npc)) {
Billboard.deleteFrom(npc);
}
}
export function handleWalkAway(npc) {
let npcData = npcDataComponent.get(npc);
if (npcData.state == NPCState.FOLLOWPATH) {
return;
}
endInteraction(npc);
if (onWalkAwayCbs.get(npc)) {
onWalkAwayCbs.get(npc)();
}
}
export function playAnimation(npc, anim, loop, duration) {
let animations = Animator.getMutable(npc);
if (animations.states.filter((animation) => animation.name === anim).length == 0) {
animations.states.push({ name: anim, clip: anim, loop: loop ? loop : false });
}
let npcData = npcDataComponent.get(npc);
if (npcData.state == NPCState.FOLLOWPATH) {
utils.paths.stopPath(npc);
}
if (animTimers.has(npc)) {
utils.timers.clearTimeout(animTimers.get(npc));
animTimers.delete(npc);
}
Animator.stopAllAnimations(npc);
Animator.playSingleAnimation(npc, anim, true);
if (duration) {
animTimers.set(npc, utils.timers.setTimeout(() => {
animTimers.delete(npc);
}, 1000 * duration));
}
npcData.lastPlayedAnim = anim;
}
export function changeIdleAnim(npc, animation, play) {
let npcData = npcDataComponent.get(npc);
npcData.idleAnim = animation;
if (play) {
playAnimation(npc, animation, true);
npcDataComponent.get(npc).lastPlayedAnim = animation;
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibnBjLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL25wYy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsUUFBUSxFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQWlCLE1BQU0sRUFBVSxhQUFhLEVBQWMsWUFBWSxFQUFDLFlBQVksRUFBQyxtQkFBbUIsRUFBQyxTQUFTLEVBQWlCLE1BQU0sY0FBYyxDQUFBO0FBQ2pNLE9BQU8sRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLE1BQU0sZUFBZSxDQUFBO0FBQy9DLE9BQU8sRUFBMkIsV0FBVyxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQWUsTUFBTSxTQUFTLENBQUM7QUFDL0YsT0FBTyxLQUFLLEtBQUssTUFBTSxnQkFBZ0IsQ0FBQTtBQUN2QyxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQy9DLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxlQUFlLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDaEUsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNwQyxPQUFPLEVBQUUsU0FBUyxFQUFFLFdBQVcsRUFBRSxrQkFBa0IsRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUV0RSxNQUFNLENBQUMsTUFBTSxhQUFhLEdBQXVCLElBQUksR0FBRyxFQUFFLENBQUE7QUFDMUQsTUFBTSxDQUFDLE1BQU0sZ0JBQWdCLEdBQXFCLElBQUksR0FBRyxFQUFFLENBQUE7QUFDM0QsTUFBTSxDQUFDLElBQUksU0FBUyxHQUFVLENBQUMsQ0FBQTtBQUUvQixNQUFNLGFBQWEsR0FBRyxNQUFNLENBQUMsU0FBUyxDQUFDLGVBQWUsQ0FBQyxDQUFBO0FBQ3ZELE1BQU0sWUFBWSxHQUFHLE1BQU0sQ0FBQyxTQUFTLENBQUMsa0JBQWtCLENBQUMsQ0FBQTtBQUV6RCxNQUFNLFVBQVUsR0FBcUIsSUFBSSxHQUFHLEVBQUUsQ0FBQTtBQUM5QyxNQUFNLGFBQWEsR0FBcUIsSUFBSSxH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LFFBQVEsQ0FBQyxtQkFBbUIsQ0FBQyxHQUFHLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFBO0lBQzdDLElBQUcsUUFBUSxFQUFDO1FBQ1IsVUFBVSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsR0FBRSxFQUFFO1lBQzVDLFVBQVUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUE7UUFDMUIsQ0FBQyxFQUFFLElBQUksR0FBRyxRQUFRLENBQUMsQ0FBQyxDQUFBO0tBQ3ZCO0lBRUQsT0FBTyxDQUFDLGNBQWMsR0FBRyxJQUFJLENBQUE7QUFDakMsQ0FBQztBQUVELE1BQU0sVUFBVSxjQUFjLENBQUMsR0FBVSxFQUFFLFNBQWdCLEVBQUUsSUFBYTtJQUN0RSxJQUFJLE9BQU8sR0FBRyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUE7SUFDdkMsT0FBTyxDQUFDLFFBQVEsR0FBRyxTQUFTLENBQUE7SUFDNUIsSUFBRyxJQUFJLEVBQUM7UUFDSixhQUFhLENBQUMsR0FBRyxFQUFFLFNBQVMsRUFBRSxJQUFJLENBQUMsQ0FBQTtRQUNuQyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsY0FBYyxHQUFHLFNBQVMsQ0FBQTtLQUN2RDtBQUNMLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBBbmltYXRvciwgQXZhdGFyU2hhcGUsIEJpbGxib2FyZCwgQmlsbGJvYXJkTW9kZSwgZW5naW5lLCBFbnRpdHksIEdsdGZDb250YWluZXIsIElucHV0QWN0aW9uLE1lc2hDb2xsaWRlcixNZXNoUmVuZGVyZXIscG9pbnRlckV2ZW50c1N5c3RlbSxUcmFuc2Zvcm0sIFRyYW5zZm9ybVR5cGUgfSBmcm9tICdAZGNsL3Nkay9lY3MnXG5pbXBvcnQgeyBDb2xvcjMsIFZlY3RvcjMgfSBmcm9tICdAZGNsL3Nkay9tYXRoJ1xuaW1wb3J0IHsgRm9sbG93UGF0aERhdGEsIE5QQ0RhdGEsIE5QQ1BhdGhUeXBlLCBOUENTdGF0ZSwgTlBDVHlwZSwgVHJpZ2dlckRhdGEgfSBmcm9tICcuL3R5cGVzJztcbmltcG9ydCAqIGFzIHV0aWxzIGZyb20gJ0BkY2wtc2RrL3V0aWxzJ1xuaW1wb3J0IHsgSXNGb2xsb3dpbmdQYXRoIH0gZnJvbSAnLi9jb21wb25lbnRzJztcbmltcG9ydCB7IGhhbmRsZURpYWxvZ1R5cGluZywgaGFuZGxlUGF0aFRpbWVzIH0gZnJvbSAnLi9zeXN0ZW1zJztcbmltcG9ydCB7IGNyZWF0ZURpYWxvZyB9IGZyb20gJy4vdWknO1xuaW1wb3J0IHsgYWRkRGlhbG9nLCBjbG9zZURpYWxvZywgbnBjRGlhbG9nQ29tcG9uZW50IH0gZnJvbSAnLi9kaWFsb2cnO1xuXG5leHBvcnQgY29uc3Qgd2Fsa2luZ1RpbWVyczogTWFwPEVudGl0eSxudW1iZXI+ID0gbmV3IE1hcCgpXG5leHBvcnQgY29uc3QgbnBjRGF0YUNvbXBvbmVudDogTWFwPEVudGl0eSwgYW55PiA9IG5ldyBNYXAoKVxuZXhwb3J0IGxldCBhY3RpdmVOUEM6bnVtYmVyID0gMFxuXG5jb25zdCB3YWxraW5nU3lzdGVtID0gZW5naW5lLmFkZFN5c3RlbShoYW5kbGVQYXRoVGltZXMpXG5jb25zdCBkaWFsb2dTeXN0ZW0gPSBlbmdpbmUuYWRkU3lzdGVtKGhhbmRsZURpYWxvZ1R5cGluZylcblxuY29uc3QgaXNDb29sZG93bjogTWFwPEVudGl0eSwgYW55PiA9IG5ldyBNYXAoKVxuY29uc3Qgb25BY3RpdmF0ZUNiczogTWFwPEVudGl0eSwgYW55PiA9IG5ldyBNYXAoKVxuY29uc3Qgb25XYWxrQXdheUNiczogTWFwPEVudGl0eSwgYW55PiA9IG5ldyBNYXAoKVxuY29uc3QgYW5pbVRpbWVyczogTWFwPEVudGl0eSxhbnk+ID0gbmV3IE1hcCgpXG5jb25zdCBwb2ludFJlYWNoZWRDYWxsYmFja3M6IE1hcDxFbnRpdHksIGFueT4gPSBuZXcgTWFwKClcbmNvbnN0IG9uRmluaXNoQ2FsbGJhY2tzOiBNYXA8RW50aXR5LCBhbnk+ID0gbmV3IE1hcCgpXG5cbmV4cG9ydCBmdW5jdGlvbiBzaG93RGVidWcoZGVidWc6Ym9vbGVhbil7XG4gICAgdXRpbHMudHJpZ2dlcnMuZW5hYmxlRGVidWdEcmF3KGRlYnVnKVxufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0RGF0YShucGM6RW50aXR5KXtcbiAgICByZXR1cm4gbnBjRGF0YUNvbXBvbmVudC5nZXQobnBjKVxufVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlKFxuICAgIHRyYW5zZm9ybTogVHJhbnNmb3JtVHlwZSxcbiAgICBkYXRhOiBOUENEYXRhXG4pe1xuICAgIGxldCBucGMgPSBlbmdpbmUuYWRkRW50aXR5KClcblxuICAgIFRyYW5zZm9ybS5jcmVhdGUobnBjLCB0cmFuc2Zvcm0pXG5cbiAgICBucGNEYXRhQ29tcG9uZW50LnNldChucGMse1xuICAgICAgICBpbnRyb2R1Y2VkOiBmYWxzZSxcbiAgICAgICAgaW5Db29sZG93bjogZmFsc2UsXG4gICAgICAgIGNvb2xEb3duRHVyYXRpb246IGRhdGEgJiYgZGF0YS5jb29sRG93bkR1cmF0aW9uID8gZGF0YS5jb29sRG93bkR1cmF0aW9uIDogNSxcbiAgICAgICAgZmFjZVVzZXI6ZGF0YS5mYWNlVXNlcixcbiAgICAgICAgd2Fsa2luZ1NwZWVkOjIsXG4gICAgICAgIHdhbGtpbmdBbmltOiBkYXRhICYmIGRhdGEud2Fsa2luZ0FuaW0gPyBkYXRhLndhbGtpbmdBbmltIDogdW5kZWZpbmVkLFxuICAgICAgICBidWJibGVIZWlnaHQ6MixcbiAgICAgICAgcGF0aERhdGE6IGRhdGEucGF0aERhdGEgPyBkYXRhLnBhdGhEYXRhIDogdW5kZWZpbmVkLFxuICAgICAgICBjdXJyZW50UGF0aERhdGE6IFtdLFxuICAgICAgICBtYW51YWxTdG9wOmZhbHNlLFxuICAgICAgICBwYXRoSW5kZXg6MCxcbiAgICAgICAgc3RhdGU6TlBDU3RhdGUuU1RBTkRJTkdcbiAgICB9KVxuXG4gICAgaWYoZGF0YSAmJiBkYXRhLm5vVUkpe31cbiAgICBlbHNlIGlmKGRhdGEgJiYgZGF0YS5wb3J0cmFpdCl7fVxuICAgIGVsc2V7XG4gICAgICAgIGFkZERpYWxvZyhucGMsIGRhdGEgJiYgZGF0YS5kaWFsb2dTb3VuZCA/IGRhdGEuZGlhbG9nU291bmQgOiB1bmRlZmluZWQpXG4gICAgICAgIGNyZWF0ZURpYWxvZyhucGMpXG4gICAgfVxuXG4gICAgb25BY3RpdmF0ZUNicy5zZXQobnBjLCAoKT0+e1xuICAgICAgICBkYXRhLm9uQWN0aXZhdGUoKVxuICAgIH0pXG5cbiAgICBpZiAoZGF0YSAmJiBkYXRhLm9uV2Fsa0F3YXkpIHtcbiAgICAgICAgb25XYWxrQXdheUNicy5zZXQobnBjLCAoKT0+e1xuICAgICAgICAgICAgaWYoIWRhdGEgfHwgIWRhdGEuY29udGludWVPbldhbGtBd2F5KXtcbiAgICAgICAgICAgICAgICBpZihucGNEaWFsb2dDb21wb25lbnQuaGFzKG5wYykpe1xuICAgICAgICAgICAgICAgICAgICBucGNEaWFsb2dDb21wb25lbnQuZ2V0KG5wYykudmlzaWJsZSA9IGZhbHNlXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZXtcbiAgICAgICAgICAgICAgICBpZihucGNEaWFsb2dDb21wb25lbnQuaGFzKG5wYykpe1xuICAgICAgICAgICAgICAgICAgICBucGNEaWFsb2dDb21wb25lbnQuZ2V0KG5wYykudmlzaWJsZSA9IGZhbHNlXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZGF0YS5vbldhbGtBd2F5ISgpXG4gICAgICAgIH0pXG4gICAgfVxuXG4gICAgYWRkTlBDQm9uZXMobnBjLCBkYXRhKVxuICAgIGFkZENsaWNrUmVhY3Rpb25zKG5wYywgZGF0YSlcbiAgICBhZGRUcmlnZ2VyQXJlYShucGMsIGRhdGEpXG4gICAgXG4gICAgaWYgKGRhdGEgJiYgZGF0YS5wYXRoRGF0YSAmJiBkYXRhLnBhdGhEYXRhLnNwZWVkKSB7XG4gICAgICAgIGxldCBucGNEYXRhID0gbnBjRGF0YUNvbXBvbmVudC5nZXQobnBjKVxuICAgICAgICBucGNEYXRhLndhbGtpbmdTcGVlZCA9IGRhdGEucGF0aERhdGEuc3BlZWRcbiAgICB9XG5cbiAgICBpZiAoZGF0YSAmJiBkYXRhLmNvb2xEb3duRHVyYXRpb24pIHtcbiAgICAgICAgbGV0IG5wY0RhdGEgPSBucGNEYXRhQ29tcG9uZW50LmdldChucGMpXG4gICAgICAgIG5wY0RhdGEuY29vbERvd25EdXJhdGlvbiA9IGRhdGEuY29vbERvd25EdXJhdGlvblxuICAgIH1cblxuICAgIGlmIChkYXRhICYmIGRhdGEucGF0aERhdGEpe1xuICAgICAgICBsZXQgbnBjRGF0YSA9IG5wY0RhdGFDb21wb25lbnQuZ2V0KG5wYylcbiAgICAgICAgLy9ucGNEYXRhLmN1cnJlbnRQYXRoRGF0YSA9IG5wY0RhdGEucGF0aERhdGFcbiAgICAgICAgZm9sbG93UGF0aChucGMsIG5wY0RhdGEucGF0aERhdGEpXG4gICAgfVxuXG4gICAgcmV0dXJuIG5wY1xufVxuXG5mdW5jdGlvbiBhZGROUENCb25lcyhucGM6RW50aXR5LCBkYXRhOk5QQ0RhdGEpe1xuICAgIHN3aXRjaChkYXRhLnR5cGUpe1xuICAgICAgICBjYXNlIE5QQ1R5cGUuQVZBVEFSOlxuICAgICAgICAgICAgQXZhdGFyU2hhcGUuY3JlYXRlKG5wYywge1xuICAgICAgICAgICAgICAgIGlkOiBcIm5wY1wiLFxuICAgICAgICAgICAgICAgIG5hbWU6IFwiTlBDXCIsXG4gICAgICAgICAgICAgICAgYm9keVNoYXBlOlwidXJuOmRlY2VudHJhbGFuZDpvZmYtY2hhaW46YmFzZS1hdmF0YXJzOkJhc2VNYWxlXCIsXG4gICAgICAgICAgICAgICAgZW1vdGVzOiBbXSxcbiAgICAgICAgICAgICAgICB3ZWFyYWJsZXM6IFtcbiAgICAgICAgICAgICAgICAgICAgXCJ1cm46ZGVjZW50cmFsYW5kOm9mZi1jaGFpbjpiYXNlLWF2YXRhcnM6Zl9leWVzXzAwXCIsXG4gICAgICAgICAgICAgICAgICAgIFwidXJuOmRlY2VudHJhbGFuZDpvZmYtY2hhaW46YmFzZS1hdmF0YXJzOmZfZXllYnJvd3NfMDBcIixcbiAgICAgICAgICAgICAgICAgICAgXCJ1cm46ZGVjZW50cmFsYW5kOm9mZi1jaGFpbjpiYXNlLWF2YXRhcnM6Zl9tb3V0aF8wMFwiLFxuICAgICAgICAgICAgICAgICAgICBcInVybjpkZWNlbnRyYWxhbmQ6b2ZmLWNoYWluOmJhc2UtYXZhdGFyczpjb21meV9zcG9ydF9zYW5kYWxzXCIsXG4gICAgICAgICAgICAgICAgICAgIFwidXJuOmRlY2VudHJhbGFuZDpvZmYtY2hhaW46YmFzZS1hdmF0YXJzOnNvY2Nlcl9wYW50c1wiLFxuICAgICAgICAgICAgICAgICAgICBcInVybjpkZWNlbnRyYWxhbmQ6b2ZmLWNoYWluOmJhc2UtYXZhdGFyczplbGVnYW50X3N3ZWF0ZXJcIixcbiAgICAgICAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlIE5QQ1R5cGUuQ1VTVE9NOlxuICAgICAgICAgICAgR2x0ZkNvbnRhaW5lci5jcmVhdGUobnBjLCB7IFxuICAgICAgICAgICAgICAgIHNyYzogZGF0YSAmJiBkYXRhLm1vZGVsID8gZGF0YS5tb2RlbCA6IFwiXCIgXG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgQW5pbWF0b3IuY3JlYXRlKG5wYywge1xuICAgICAgICAgICAgICAgIHN0YXRlczpbe1xuICAgICAgICAgICAgICAgICAgICBuYW1lOmRhdGEgJiYgZGF0YS5pZGxlQW5pbSA/IGRhdGEuaWRsZUFuaW0gOiAnSWRsZScsXG4gICAgICAgICAgICAgICAgICAgIGNsaXA6ZGF0YSAmJiBkYXRhLmlkbGVBbmltID8gZGF0YS5pZGxlQW5pbSA6ICdJZGxlJyxcbiAgICAgICAgICAgICAgICAgICAgbG9vcDp0cnVlXG4gICAgICAgICAgICAgICAgfV1cbiAgICAgICAgICAgIH0pXG5cbiAgICAgICAgICAgIG5wY0RhdGFDb21wb25lbnQuZ2V0KG5wYykuaWRsZUFuaW0gPSBkYXRhICYmIGRhdGEuaWRsZUFuaW0gPyBkYXRhLmlkbGVBbmltIDogJ0lkbGUnXG4gICAgICAgICAgICBBbmltYXRvci5wbGF5U2luZ2xlQW5pbWF0aW9uKG5wYywgbnBjRGF0YUNvbXBvbmVudC5nZXQobnBjKS5pZGxlQW5pbSlcblxuICAgICAgICAgICAgbGV0IG5wY0RhdGEgPSBucGNEYXRhQ29tcG9uZW50LmdldChucGMpXG4gICAgICAgICAgICBucGNEYXRhLmxhc3RQbGF5ZWRBbmltID0gbnBjRGF0YUNvbXBvbmVudC5nZXQobnBjKS5pZGxlQW5pbVxuXG4gICAgICAgICAgICBpZiAoZGF0YSAmJiBkYXRhLndhbGtpbmdBbmltKSB7XG4gICAgICAgICAgICAgICAgbnBjRGF0YUNvbXBvbmVudC5nZXQobnBjKS53YWxraW5nQW5pbSA9IGRhdGEud2Fsa2luZ0FuaW1cbiAgICAgICAgICAgICAgICBsZXQgYW5pbWF0aW9ucyA9IEFuaW1hdG9yLmdldE11dGFibGUobnBjKVxuICAgICAgICAgICAgICAgIGFuaW1hdGlvbnMuc3RhdGVzLnB1c2goe25hbWU6ZGF0YS53YWxraW5nQW5pbSwgY2xpcDogZGF0YS53YWxraW5nQW5pbSwgbG9vcDp0cnVlfSlcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSBOUENUeXBlLkJMQU5LOlxuICAgICAgICAgICAgTWVzaFJlbmRlcmVyLnNldEJveChucGMpXG4gICAgICAgICAgICBNZXNoQ29sbGlkZXIuc2V0Qm94KG5wYylcbiAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgfVxufVxuXG5mdW5jdGlvbiBhZGRDbGlja1JlYWN0aW9ucyhucGM6RW50aXR5LCBkYXRhOk5QQ0RhdGEpe1xuICAgIGxldCBhY3RpdmF0ZUJ1dHRvbiA9IGRhdGEgJiYgZGF0YS5vbmx5Q2xpY2tUcmlnZ2VyID8gSW5wdXRBY3Rpb24uSUFfUE9JTlRFUiA6IElucHV0QWN0aW9uLklBX1BSSU1BUllcblxuICAgIHBvaW50ZXJFdmVudHNTeXN0ZW0ub25Qb2ludGVyRG93bihcbiAgICAgICAgbnBjLFxuICAgICAgICBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAoaXNDb29sZG93bi5oYXMobnBjKSB8fCAobnBjRGlhbG9nQ29tcG9uZW50LmdldChucGMpLnZpc2libGUpKSByZXR1cm5cbiAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiY2xpY2tlZCBlbnRpdHlcIilcbiAgICAgICAgICAgIGFjdGl2YXRlKG5wYylcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgICAgYnV0dG9uOiBhY3RpdmF0ZUJ1dHRvbixcbiAgICAgICAgICAgIGhvdmVyVGV4dDogZGF0YSAmJiBkYXRhLmhvdmVyVGV4dCA/IGRhdGEuaG92ZXJUZXh0IDogJ1RhbGsnLFxuICAgICAgICAgICAgc2hvd0ZlZWRiYWNrOiBkYXRhICYmIGRhdGEub25seUV4dGVybmFsVHJpZ2dlciA/IGZhbHNlIDogdHJ1ZSxcbiAgICAgICAgfVxuICAgICAgICApXG5cbiAgICAgICAgaWYgKGRhdGEgJiYgZGF0YS5vbmx5RXh0ZXJuYWxUcmlnZ2VyKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKFwib25seSBleHRlcm5hbCB0cmlnZ2VyLCByZW1vdmVkIHBvaW50ZXJcIilcbiAgICAgICAgcG9pbnRlckV2ZW50c1N5c3RlbS5yZW1vdmVPblBvaW50ZXJEb3duKG5wYylcbiAgICAgICAgfSBcbn1cblxuZnVuY3Rpb24gYWRkVHJpZ2dlckFyZWEobnBjOkVudGl0eSwgZGF0YTpOUENEYXRhKXtcblxuICAgICAgICBsZXQgdHJpZ2dlckRhdGE6IFRyaWdnZXJEYXRhID0ge31cblxuICAgICAgICBpZiAoIWRhdGEgfHwgKGRhdGEgJiYgIWRhdGEub25seUV4dGVybmFsVHJpZ2dlciAmJiAhZGF0YS5vbmx5Q2xpY2tUcmlnZ2VyICYmICFkYXRhLm9ubHlFVHJpZ2dlcikpe1xuICAgICAgICBvbkFjdGl2YXRlQ2JzLnNldChucGMsICgpPT57XG4gICAgICAgICAgICBpZiAoaXNDb29sZG93bi5oYXMobnBjKSkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKG5wYywgJyBpbiBjb29sZG93bicpXG4gICAgICAgICAgICAgICAgcmV0dXJuXG4gICAgICAgICAgICB9IFxuICAgICAgICAgICAgZWxzZSBpZiAoXG4gICAgICAgICAgICAgICAgKG5wY0RpYWxvZ0NvbXBvbmVudC5oYXMobnBjKSAmJiBucGNEaWFsb2dDb21wb25lbnQuZ2V0KG5wYykudmlzaWJsZSkgfHxcbiAgICAgICAgICAgICAgICAoZGF0YSAmJiBkYXRhLm9ubHlFeHRlcm5hbFRyaWdnZXIpIHx8XG4gICAgICAgICAgICAgICAgKGRhdGEgJiYgZGF0YS5vbmx5Q2xpY2tUcmlnZ2VyKVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkYXRhLm9uQWN0aXZhdGUoKVxuICAgICAgICB9KVxuICAgICAgICB0cmlnZ2VyRGF0YS5vbkNhbWVyYUVudGVyID0gb25BY3RpdmF0ZUNicy5nZXQobnBjKVxuICAgICAgICB9XG5cbiAgICAvLyB3aGVuIGV4aXRpbmcgdHJpZ2dlclxuICAgIGlmICghZGF0YSB8fCAoZGF0YSAmJiAhZGF0YS5jb250aW51ZU9uV2Fsa0F3YXkpKSB7XG4gICAgICAgIHRyaWdnZXJEYXRhLm9uQ2FtZXJhRXhpdCA9ICgpID0+IHtcbiAgICAgICAgICAgIGhhbmRsZVdhbGtBd2F5KG5wYylcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIHdoZW4gZW50ZXJpbmcgdHJpZ2dlclxuICAgIGlmIChcbiAgICAgICAgIWRhdGEgfHxcbiAgICAgICAgKGRhdGEgJiYgIWRhdGEub25seUV4dGVybmFsVHJpZ2dlciAmJiAhZGF0YS5vbmx5Q2xpY2tUcmlnZ2VyICYmICFkYXRhLm9ubHlFVHJpZ2dlcilcbiAgICApIHtcbiAgICAgICAgdHJpZ2dlckRhdGEub25DYW1lcmFFbnRlciA9ICgpID0+IHtcbiAgICAgICAgICAgIGlmIChpc0Nvb2xkb3duLmhhcyhucGMpKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2cobnBjLCAnIGluIGNvb2xkb3duJylcbiAgICAgICAgICAgICAgICByZXR1cm5cbiAgICAgICAgICAgIH0gXG4gICAgICAgICAgICAvLyBlbHNlIGlmIChcbiAgICAgICAgICAgIC8vICAgICAodGhpcy5kaWFsb2cgJiYgdGhpcy5kaWFsb2cuaXNEaWFsb2dPcGVuKSB8fFxuICAgICAgICAgICAgLy8gICAgIChkYXRhICYmIGRhdGEub25seUV4dGVybmFsVHJpZ2dlcikgfHxcbiAgICAgICAgICAgIC8vICAgICAoZGF0YSAmJiBkYXRhLm9ubHlDbGlja1RyaWdnZXIpXG4gICAgICAgICAgICAvLyApIHtcbiAgICAgICAgICAgIC8vICAgICByZXR1cm5cbiAgICAgICAgICAgIC8vIH1cbiAgICAgICAgICAgIGFjdGl2YXRlKG5wYylcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIGFkZCB0cmlnZ2VyXG4gICAgaWYgKHRyaWdnZXJEYXRhLm9uQ2FtZXJhRW50ZXIgfHwgdHJpZ2dlckRhdGEub25DYW1lcmFFeGl0KSB7XG4gICAgICAgIHV0aWxzLnRyaWdnZXJzLmFkZFRyaWdnZXIobnBjLDI1NCwxLFt7dHlwZTonc3BoZXJlJywgcG9zaXRpb246IFZlY3RvcjMuWmVybygpLCByYWRpdXM6IGRhdGEucmVhY3REaXN0YW5jZSAhPSB1bmRlZmluZWQgPyBkYXRhLnJlYWN0RGlzdGFuY2UgOiA2fV0sIHRyaWdnZXJEYXRhLm9uQ2FtZXJhRW50ZXIgPyB0cmlnZ2VyRGF0YS5vbkNhbWVyYUVudGVyIDogdW5kZWZpbmVkLCB0cmlnZ2VyRGF0YS5vbkNhbWVyYUV4aXQgPyB0cmlnZ2VyRGF0YS5vbkNhbWVyYUV4aXQgOiB1bmRlZmluZWQsIENvbG9yMy5SZWQoKSlcbiAgICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBmb2xsb3dQYXRoKG5wYzpFbnRpdHksIGRhdGE/OkZvbGxvd1BhdGhEYXRhKXtcbiAgICAgICAgXG4gICAgbGV0IG5wY0RhdGEgPSBucGNEYXRhQ29tcG9uZW50LmdldChucGMpXG4gICAgbGV0IHBhdGg6YW55W10gPVtdXG5cbiAgICBpZihkYXRhKXtcbiAgICAgICAgbnBjRGF0YS5wYXRoRGF0YSA9IGRhdGFcblxuICAgICAgICBpZihucGNEYXRhLmZhY2VVc2VyKXtcbiAgICAgICAgICAgIEJpbGxib2FyZC5kZWxldGVGcm9tKG5wYylcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGRhdGEuc3RhcnRpbmdQb2ludCl7XG4gICAgICAgICAgICBkYXRhLnBhdGg/LnNwbGljZSgwLGRhdGEuc3RhcnRpbmdQb2ludCAtIDEpXG4gICAgICAgIH1cblxuICAgICAgICBsZXQgcG9zID0gVHJhbnNmb3JtLmdldChucGMpLnBvc2l0aW9uXG4gICAgICAgIHBhdGgucHVzaChWZWN0b3IzLmNyZWF0ZShwb3MueCwgcG9zLnksIHBvcy56KSlcbiAgICAgICAgZGF0YS5wYXRoPy5mb3JFYWNoKChwKT0+e1xuICAgICAgICAgICAgcGF0aC5wdXNoKHApXG4gICAgICAgIH0pXG5cbiAgICAgICAgb25GaW5pc2hDYWxsYmFja3Muc2V0KG5wYywoKT0+e1xuICAgICAgICAgICAgY29uc29sZS5sb2coJ29uIGZpbmlzaGVkIGNhbGxiYWNrJylcbiAgICAgICAgICAgIGlmKGRhdGEgJiYgZGF0YS5vbkZpbmlzaENhbGxiYWNrICYmICFkYXRhLmxvb3Ape1xuICAgICAgICAgICAgICAgIGRhdGEub25GaW5pc2hDYWxsYmFja1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc3RvcFBhdGgobnBjKVxuICAgICAgICB9KVxuXG4gICAgICAgIHBvaW50UmVhY2hlZENhbGxiYWNrcy5zZXQobnBjLCAoKT0+e1xuICAgICAgICAgICAgY29uc29sZS5sb2coJ29uIHBvaW50IHJlYWNoZWQgY2FsbGJhY2snKVxuICAgICAgICAgICAgbGV0IGRhdGEgPSBucGNEYXRhQ29tcG9uZW50LmdldChucGMpXG4gICAgICAgICAgICBkYXRhLnBhdGhJbmRleCArPSAxXG4gICAgICAgICAgICBkYXRhLm9uUmVhY2hlZFBvaW50Q2FsbGJhY2sgPyBkYXRhLm9uUmVhY2hlZFBvaW50Q2FsbGJhY2sgOiB1bmRlZmluZWRcbiAgICAgICAgfSlcbiAgICAgICAgd2Fsa05QQyhucGMsIG5wY0RhdGEsIGRhdGEucGF0aFR5cGUhLCBkYXRhLnRvdGFsRHVyYXRpb24sIHBhdGgsIHBvaW50UmVhY2hlZENhbGxiYWNrcy5nZXQobnBjKSwgb25GaW5pc2hDYWxsYmFja3MuZ2V0KG5wYykpXG4gICAgfWVsc2V7XG4gICAgICAgIGlmKG5wY0RhdGEubWFudWFsU3RvcCl7XG4gICAgICAgICAgICBjb25zb2xlLmxvZygnd2UgaGF2ZSBtYW51YWwgc3RvcCwgbmVlZCB0byBwaWNrIGJhY2sgdXAgd2hlcmUgd2UgbGVmdCBvZmYnKVxuICAgICAgICB9XG4gICAgICAgIGVsc2V7XG4gICAgICAgICAgICBjb25zb2xlLmxvZygnd2UgYXJlIHRyeWluZyB0byBmb2xsb3cgYSBwYXRoIHdpdG91dCBzdGFydGluZyBvbmUgcHJpb3InKVxuICAgICAgICB9XG4gICAgfVxuICAgIH1cbi8vXG5mdW5jdGlvbiB3YWxrTlBDKG5wYzpFbnRpdHksIG5wY0RhdGE6YW55LCB0eXBlOk5QQ1BhdGhUeXBlLCBkdXJhdGlvbjpudW1iZXIsIHBhdGg6VmVjdG9yM1tdLCBwb2ludFJlYWNoZWRDYWxsYmFjaz86YW55LCBmaW5pc2hlZENhbGxiYWNrPzphbnkpe1xuICAgIC8vXG4gICAgaWYoSXNGb2xsb3dpbmdQYXRoLmhhcyhucGMpKXtcbiAgICAgICAgSXNGb2xsb3dpbmdQYXRoLmRlbGV0ZUZyb20obnBjKVxuICAgICAgICB3YWxraW5nVGltZXJzLmRlbGV0ZShucGMpXG4gICAgfVxuICAgIElzRm9sbG93aW5nUGF0aC5jcmVhdGUobnBjKVxuXG4gICAgaWYodHlwZSl7XG4gICAgICAgIGlmKHR5cGU9PSBOUENQYXRoVHlwZS5SSUdJRF9QQVRIKXtcbiAgICAgICAgICAgIHV0aWxzLnBhdGhzLnN0YXJ0U3RyYWlnaHRQYXRoKG5wYywgcGF0aCwgZHVyYXRpb24sdHJ1ZSxcbiAgICAgICAgICAgICAgICAoKT0+e2ZpbmlzaGVkQ2FsbGJhY2soKX0sICgpPT57cG9pbnRSZWFjaGVkQ2FsbGJhY2soKX0pXG4gICAgICAgIH1cbiAgICAgICAgZWxzZXtcbiAgICAgICAgICAgIHV0aWxzLnBhdGhzLnN0YXJ0U21vb3RoUGF0aChucGMsIHBhdGgsIGR1cmF0aW9uLCAzMCwgdHJ1ZSwgXG4gICAgICAgICAgICAgICAgKCk9PntmaW5pc2hlZENhbGxiYWNrKCl9LCAoKT0+e3BvaW50UmVhY2hlZENhbGxiYWNrKCl9KVxuICAgICAgICAgICAgfVxuICAgIH1cbiAgICBlbHNle1xuICAgICAgICB1dGlscy5wYXRocy5zdGFydFNtb290aFBhdGgobnBjLCBwYXRoLCBkdXJhdGlvbiwgMjAsIHRydWUsIFxuICAgICAgICAgICAgKCk9PntmaW5pc2hlZENhbGxiYWNrKCl9LCAoKT0+e3BvaW50UmVhY2hlZENhbGxiYWNrKCl9KVxuICAgIH0gICBcblxuICAgIGlmIChucGNEYXRhLndhbGtpbmdBbmltKSB7XG4gICAgICAgIC8vIGlmICh0aGlzLmVuZEFuaW1UaW1lci5oYXNDb21wb25lbnQoTlBDRGVsYXkpKSB7XG4gICAgICAgIC8vICAgdGhpcy5lbmRBbmltVGltZXIucmVtb3ZlQ29tcG9uZW50KE5QQ0RlbGF5KVxuICAgICAgICAvLyB9XG4gICAgICAgIEFuaW1hdG9yLnBsYXlTaW5nbGVBbmltYXRpb24obnBjLCBucGNEYXRhQ29tcG9uZW50LmdldChucGMpLndhbGtpbmdBbmltLCB0cnVlKVxuICAgICAgICBucGNEYXRhLmxhc3RQbGF5ZWRBbmltID0gbnBjRGF0YUNvbXBvbmVudC5nZXQobnBjKS53YWxraW5nQW5pbVxuICAgICAgfVxuICAgIG5wY0RhdGEuc3RhdGUgPSBOUENTdGF0ZS5GT0xMT1dQQVRIXG4gICAgY29uc29sZS5sb2coJ2RlYnVnIGhlcmUnKVxufVxuXG5leHBvcnQgZnVuY3Rpb24gc3RvcFdhbGtpbmcobnBjOkVudGl0eSwgZHVyYXRpb24/OiBudW1iZXIsIGZpbmlzaGVkPzpib29sZWFuKSB7XG4gICAgbGV0IG5wY0RhdGEgPSBucGNEYXRhQ29tcG9uZW50LmdldChucGMpXG4gICAgbnBjRGF0YS5zdGF0ZSA9IE5QQ1N0YXRlLlNUQU5ESU5HXG4gICAgbnBjRGF0YS5tYW51YWxTdG9wID0gdHJ1ZVxuXG4gICAgc3RvcFBhdGgobnBjKVxuXG4gICAgaWYgKGR1cmF0aW9uKSB7XG4gICAgICAgIHV0aWxzLnRpbWVycy5zZXRUaW1lb3V0KCgpPT57XG4gICAgICAgICAgICAvL2lmICh0aGlzLmRpYWxvZyAmJiB0aGlzLmRpYWxvZy5pc0RpYWxvZ09wZW4pIHJldHVyblxuICAgICAgICAgICAgaWYobnBjRGF0YS5wYXRoKXtcbiAgICAgICAgICAgICAgICBBbmltYXRvci5zdG9wQWxsQW5pbWF0aW9ucyhucGMsIHRydWUpXG4gICAgICAgICAgICAgICAgaWYobnBjRGF0YUNvbXBvbmVudC5nZXQobnBjKS53YWxraW5nQW5pbSl7XG4gICAgICAgICAgICAgICAgICAgIEFuaW1hdG9yLnBsYXlTaW5nbGVBbmltYXRpb24obnBjLCBucGNEYXRhQ29tcG9uZW50LmdldChucGMpLndhbGtpbmdBbmltLHRydWUpXG4gICAgICAgICAgICAgICAgICAgIG5wY0RhdGEubGFzdFBsYXllZEFuaW0gPSBucGNEYXRhQ29tcG9uZW50LmdldChucGMpLndhbGtpbmdBbmltXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGxldCBkdXJhdGlvbiA9IG5wY0RhdGEucGF0aERhdGEudG90YWxEdXJhdGlvblxuICAgICAgICAgICAgICAgIGxldCBjdXJyZW50VGltZXI6bnVtYmVyID0gd2Fsa2luZ1RpbWVycy5