dcl-npc-toolkit
Version:
A collection of tools for creating Non-Player-Characters (NPCs). These are capable of having conversations with the player, and play different animations.
125 lines • 21.8 kB
JavaScript
import { engine, EntityState, Schemas, Transform } from '@dcl/sdk/ecs';
import { Scalar, Vector3, Quaternion } from '@dcl/sdk/math';
import { createCatmullRomSpline } from './math';
function createPaths(targetEngine) {
const FollowPath = targetEngine.defineComponent('dcl.utils.FollowPath', {
points: Schemas.Array(Schemas.Vector3),
faceDirection: Schemas.Boolean,
speed: Schemas.Number,
normalizedTime: Schemas.Number,
currentIndex: Schemas.Number,
segmentTimes: Schemas.Array(Schemas.Number),
curveSegmentCount: Schemas.Number
});
const finishCbs = new Map();
const pointReachedCbs = new Map();
function unregisterEntity(entity) {
finishCbs.delete(entity);
pointReachedCbs.delete(entity);
FollowPath.deleteFrom(entity);
}
function system(dt) {
const deadPaths = [];
const pointReachedPaths = [];
for (const entity of finishCbs.keys()) {
if (targetEngine.getEntityState(entity) == EntityState.Removed || !FollowPath.has(entity)) {
unregisterEntity(entity);
continue;
}
const transform = Transform.getMutable(entity);
const path = FollowPath.getMutable(entity);
path.normalizedTime = Scalar.clamp(path.normalizedTime + dt * path.speed, 0, 1);
if (path.normalizedTime >= 1)
deadPaths.push(entity);
while (path.normalizedTime >= path.segmentTimes[path.currentIndex] &&
path.currentIndex < path.points.length - 1) {
if (path.faceDirection) {
const direction = Vector3.subtract(path.points[path.currentIndex + 1], path.points[path.currentIndex]);
transform.rotation = Quaternion.lookRotation(direction);
}
if (path.currentIndex > 0 && path.currentIndex % path.curveSegmentCount == 0) {
const pointIndex = path.currentIndex / path.curveSegmentCount;
const pointCoords = path.points[path.currentIndex];
const nextPointCoords = path.points[path.currentIndex + path.curveSegmentCount];
pointReachedPaths.push({ entity: entity, index: pointIndex, coords: pointCoords, nextCoords: nextPointCoords });
}
path.currentIndex += 1;
}
const timeDiff = path.segmentTimes[path.currentIndex] - path.segmentTimes[path.currentIndex - 1];
const coef = (path.segmentTimes[path.currentIndex] - path.normalizedTime) / timeDiff;
transform.position = Vector3.lerp(path.points[path.currentIndex], path.points[path.currentIndex - 1], coef);
}
for (const pointReached of pointReachedPaths) {
const callback = pointReachedCbs.get(pointReached.entity);
if (callback) {
callback(pointReached.index, pointReached.coords, pointReached.nextCoords);
}
}
for (const entity of deadPaths) {
const callback = finishCbs.get(entity);
unregisterEntity(entity);
if (callback)
callback();
}
}
targetEngine.addSystem(system);
function startPath(entity, points, duration, faceDirection, curveSegmentCount, onFinishCallback, onPointReachedCallback) {
if (points.length < 2)
throw new Error('At least 2 points are required to form a path.');
if (duration == 0)
throw new Error('Path duration must not be zero');
if (curveSegmentCount) {
const loop = Vector3.equals(points[0], points[points.length - 1]);
if (loop) {
points.pop();
points.unshift(points.pop());
}
points = createCatmullRomSpline(points, curveSegmentCount, loop);
}
else {
curveSegmentCount = 1;
}
finishCbs.set(entity, onFinishCallback);
pointReachedCbs.set(entity, onPointReachedCallback);
let totalLength = 0;
const segmentLengths = [];
for (let i = 0; i < points.length - 1; i++) {
let sqDist = Vector3.distance(points[i], points[i + 1]);
totalLength += sqDist;
segmentLengths.push(sqDist);
}
const segmentTimes = [0];
for (let i = 0; i < segmentLengths.length; i++) {
segmentTimes.push(segmentLengths[i] / totalLength + segmentTimes[i]);
}
FollowPath.createOrReplace(entity, {
points: points,
segmentTimes: segmentTimes,
curveSegmentCount: curveSegmentCount,
speed: 1 / duration,
normalizedTime: 0,
currentIndex: 0,
faceDirection: faceDirection
});
}
return {
startStraightPath(entity, points, duration, faceDirection, onFinishCallback, onPointReachedCallback) {
return startPath(entity, points, duration, faceDirection, 0, onFinishCallback, onPointReachedCallback);
},
startSmoothPath(entity, points, duration, segmentCount, faceDirection, onFinishCallback, onPointReachedCallback) {
if (segmentCount < 2 || !Number.isInteger(segmentCount))
throw new Error(`segmentCount must be an integer that is greater than 2, got: ${segmentCount}`);
return startPath(entity, points, duration, faceDirection, segmentCount, onFinishCallback, onPointReachedCallback);
},
stopPath(entity) {
unregisterEntity(entity);
},
getOnFinishCallback(entity) {
if (!finishCbs.has(entity))
throw new Error(`Entity ${entity} is not registered in triggers system`);
return finishCbs.get(entity);
}
};
}
export const paths = createPaths(engine);
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGF0aC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9wYXRoLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxNQUFNLEVBQVUsV0FBVyxFQUFXLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxjQUFjLENBQUE7QUFDdkYsT0FBTyxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFBO0FBQzNELE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLFFBQVEsQ0FBQTtBQVEvQyxTQUFTLFdBQVcsQ0FBQyxZQUFxQjtJQUN4QyxNQUFNLFVBQVUsR0FBRyxZQUFZLENBQUMsZUFBZSxDQUFDLHNCQUFzQixFQUFFO1FBQ3RFLE1BQU0sRUFBRSxPQUFPLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUM7UUFDdEMsYUFBYSxFQUFFLE9BQU8sQ0FBQyxPQUFPO1FBQzlCLEtBQUssRUFBRSxPQUFPLENBQUMsTUFBTTtRQUNyQixjQUFjLEVBQUUsT0FBTyxDQUFDLE1BQU07UUFDOUIsWUFBWSxFQUFFLE9BQU8sQ0FBQyxNQUFNO1FBQzVCLFlBQVksRUFBRSxPQUFPLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUM7UUFDM0MsaUJBQWlCLEVBQUUsT0FBTyxDQUFDLE1BQU07S0FDbEMsQ0FBQyxDQUFBO0lBS0YsTUFBTSxTQUFTLEdBQXNCLElBQUksR0FBRyxFQUFFLENBQUE7SUFDOUMsTUFBTSxlQUFlLEdBQThCLElBQUksR0FBRyxFQUFFLENBQUE7SUFFNUQsU0FBUyxnQkFBZ0IsQ0FBQyxNQUFjO1FBQ3RDLFNBQVMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUE7UUFDeEIsZUFBZSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQTtRQUM5QixVQUFVLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFBO0lBQy9CLENBQUM7SUFFRCxTQUFT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O1FBQ0QsbUJBQW1CLENBQUMsTUFBYztZQUNoQyxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUM7Z0JBQ3hCLE1BQU0sSUFBSSxLQUFLLENBQUMsVUFBVSxNQUFNLHVDQUF1QyxDQUFDLENBQUE7WUFDMUUsT0FBTyxTQUFTLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFBO1FBQzlCLENBQUM7S0FDRixDQUFBO0FBQ0gsQ0FBQztBQUVELE1BQU0sQ0FBQyxNQUFNLEtBQUssR0FBRyxXQUFXLENBQUMsTUFBTSxDQUFDLENBQUEiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBlbmdpbmUsIEVudGl0eSwgRW50aXR5U3RhdGUsIElFbmdpbmUsIFNjaGVtYXMsIFRyYW5zZm9ybSB9IGZyb20gJ0BkY2wvc2RrL2VjcydcbmltcG9ydCB7IFNjYWxhciwgVmVjdG9yMywgUXVhdGVybmlvbiB9IGZyb20gJ0BkY2wvc2RrL21hdGgnXG5pbXBvcnQgeyBjcmVhdGVDYXRtdWxsUm9tU3BsaW5lIH0gZnJvbSAnLi9tYXRoJ1xuXG5cbmV4cG9ydCB0eXBlIFBhdGhzID0gUmV0dXJuVHlwZTx0eXBlb2YgY3JlYXRlUGF0aHM+XG5cbmV4cG9ydCB0eXBlIE9uRmluaXNoQ2FsbGJhY2sgPSAoKSA9PiB2b2lkXG5leHBvcnQgdHlwZSBPblBvaW50UmVhY2hlZENhbGxiYWNrID0gKHBvaW50SW5kZXg6IG51bWJlciwgcG9pbnQ6IFZlY3RvcjMsIG5leHRQb2ludDogVmVjdG9yMykgPT4gdm9pZFxuXG5mdW5jdGlvbiBjcmVhdGVQYXRocyh0YXJnZXRFbmdpbmU6IElFbmdpbmUpIHtcbiAgY29uc3QgRm9sbG93UGF0aCA9IHRhcmdldEVuZ2luZS5kZWZpbmVDb21wb25lbnQoJ2RjbC51dGlscy5Gb2xsb3dQYXRoJywge1xuICAgIHBvaW50czogU2NoZW1hcy5BcnJheShTY2hlbWFzLlZlY3RvcjMpLFxuICAgIGZhY2VEaXJlY3Rpb246IFNjaGVtYXMuQm9vbGVhbixcbiAgICBzcGVlZDogU2NoZW1hcy5OdW1iZXIsXG4gICAgbm9ybWFsaXplZFRpbWU6IFNjaGVtYXMuTnVtYmVyLFxuICAgIGN1cnJlbnRJbmRleDogU2NoZW1hcy5OdW1iZXIsXG4gICAgc2VnbWVudFRpbWVzOiBTY2hlbWFzLkFycmF5KFNjaGVtYXMuTnVtYmVyKSxcbiAgICBjdXJ2ZVNlZ21lbnRDb3VudDogU2NoZW1hcy5OdW1iZXJcbiAgfSlcblxuICB0eXBlIEZpbmlzaENhbGxiYWNrTWFwID0gTWFwPEVudGl0eSwgT25GaW5pc2hDYWxsYmFjayB8IHVuZGVmaW5lZD5cbiAgdHlwZSBPblBvaW50UmVhY2hlZENhbGxiYWNrTWFwID0gTWFwPEVudGl0eSwgT25Qb2ludFJlYWNoZWRDYWxsYmFjayB8IHVuZGVmaW5lZD5cblxuICBjb25zdCBmaW5pc2hDYnM6IEZpbmlzaENhbGxiYWNrTWFwID0gbmV3IE1hcCgpXG4gIGNvbnN0IHBvaW50UmVhY2hlZENiczogT25Qb2ludFJlYWNoZWRDYWxsYmFja01hcCA9IG5ldyBNYXAoKVxuXG4gIGZ1bmN0aW9uIHVucmVnaXN0ZXJFbnRpdHkoZW50aXR5OiBFbnRpdHkpIHtcbiAgICBmaW5pc2hDYnMuZGVsZXRlKGVudGl0eSlcbiAgICBwb2ludFJlYWNoZWRDYnMuZGVsZXRlKGVudGl0eSlcbiAgICBGb2xsb3dQYXRoLmRlbGV0ZUZyb20oZW50aXR5KVxuICB9XG5cbiAgZnVuY3Rpb24gc3lzdGVtKGR0OiBudW1iZXIpIHtcbiAgICBjb25zdCBkZWFkUGF0aHMgPSBbXVxuICAgIGNvbnN0IHBvaW50UmVhY2hlZFBhdGhzID0gW11cblxuICAgIGZvciAoY29uc3QgZW50aXR5IG9mIGZpbmlzaENicy5rZXlzKCkpIHtcbiAgICAgIGlmICh0YXJnZXRFbmdpbmUuZ2V0RW50aXR5U3RhdGUoZW50aXR5KSA9PSBFbnRpdHlTdGF0ZS5SZW1vdmVkIHx8ICFGb2xsb3dQYXRoLmhhcyhlbnRpdHkpKSB7XG4gICAgICAgIHVucmVnaXN0ZXJFbnRpdHkoZW50aXR5KVxuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuXG4gICAgICBjb25zdCB0cmFuc2Zvcm0gPSBUcmFuc2Zvcm0uZ2V0TXV0YWJsZShlbnRpdHkpXG4gICAgICBjb25zdCBwYXRoID0gRm9sbG93UGF0aC5nZXRNdXRhYmxlKGVudGl0eSlcbiAgICAgIHBhdGgubm9ybWFsaXplZFRpbWUgPSBTY2FsYXIuY2xhbXAocGF0aC5ub3JtYWxpemVkVGltZSArIGR0ICogcGF0aC5zcGVlZCwgMCwgMSlcbiAgICAgIGlmIChwYXRoLm5vcm1hbGl6ZWRUaW1lID49IDEpXG4gICAgICAgIGRlYWRQYXRocy5wdXNoKGVudGl0eSlcblxuICAgICAgd2hpbGUgKFxuICAgICAgICBwYXRoLm5vcm1hbGl6ZWRUaW1lID49IHBhdGguc2VnbWVudFRpbWVzW3BhdGguY3VycmVudEluZGV4XSAmJlxuICAgICAgICBwYXRoLmN1cnJlbnRJbmRleCA8IHBhdGgucG9pbnRzLmxlbmd0aCAtIDFcbiAgICAgICkge1xuICAgICAgICBpZiAocGF0aC5mYWNlRGlyZWN0aW9uKSB7XG4gICAgICAgICAgY29uc3QgZGlyZWN0aW9uID0gVmVjdG9yMy5zdWJ0cmFjdChwYXRoLnBvaW50c1twYXRoLmN1cnJlbnRJbmRleCArIDFdLCBwYXRoLnBvaW50c1twYXRoLmN1cnJlbnRJbmRleF0pXG4gICAgICAgICAgdHJhbnNmb3JtLnJvdGF0aW9uID0gUXVhdGVybmlvbi5sb29rUm90YXRpb24oZGlyZWN0aW9uKVxuICAgICAgICB9XG4gICAgICAgIGlmIChwYXRoLmN1cnJlbnRJbmRleCA+IDAgJiYgcGF0aC5jdXJyZW50SW5kZXggJSBwYXRoLmN1cnZlU2VnbWVudENvdW50ID09IDApIHtcbiAgICAgICAgICBjb25zdCBwb2ludEluZGV4ID0gcGF0aC5jdXJyZW50SW5kZXggLyBwYXRoLmN1cnZlU2VnbWVudENvdW50XG4gICAgICAgICAgY29uc3QgcG9pbnRDb29yZHMgPSBwYXRoLnBvaW50c1twYXRoLmN1cnJlbnRJbmRleF1cbiAgICAgICAgICBjb25zdCBuZXh0UG9pbnRDb29yZHMgPSBwYXRoLnBvaW50c1twYXRoLmN1cnJlbnRJbmRleCArIHBhdGguY3VydmVTZWdtZW50Q291bnRdXG4gICAgICAgICAgcG9pbnRSZWFjaGVkUGF0aHMucHVzaCh7ZW50aXR5OiBlbnRpdHksIGluZGV4OiBwb2ludEluZGV4LCBjb29yZHM6IHBvaW50Q29vcmRzLCBuZXh0Q29vcmRzOiBuZXh0UG9pbnRDb29yZHN9KVxuICAgICAgICB9XG4gICAgICAgIHBhdGguY3VycmVudEluZGV4ICs9IDFcbiAgICAgIH1cblxuICAgICAgY29uc3QgdGltZURpZmYgPSBwYXRoLnNlZ21lbnRUaW1lc1twYXRoLmN1cnJlbnRJbmRleF0gLSBwYXRoLnNlZ21lbnRUaW1lc1twYXRoLmN1cnJlbnRJbmRleCAtIDFdXG4gICAgICBjb25zdCBjb2VmID0gKHBhdGguc2VnbWVudFRpbWVzW3BhdGguY3VycmVudEluZGV4XSAtIHBhdGgubm9ybWFsaXplZFRpbWUpIC8gdGltZURpZmZcbiAgICAgIHRyYW5zZm9ybS5wb3NpdGlvbiA9IFZlY3RvcjMubGVycChwYXRoLnBvaW50c1twYXRoLmN1cnJlbnRJbmRleF0sIHBhdGgucG9pbnRzW3BhdGguY3VycmVudEluZGV4IC0gMV0sIGNvZWYpXG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBwb2ludFJlYWNoZWQgb2YgcG9pbnRSZWFjaGVkUGF0aHMpIHtcbiAgICAgIGNvbnN0IGNhbGxiYWNrID0gcG9pbnRSZWFjaGVkQ2JzLmdldChwb2ludFJlYWNoZWQuZW50aXR5KVxuICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgIGNhbGxiYWNrKHBvaW50UmVhY2hlZC5pbmRleCwgcG9pbnRSZWFjaGVkLmNvb3JkcywgcG9pbnRSZWFjaGVkLm5leHRDb29yZHMpXG4gICAgICB9XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBlbnRpdHkgb2YgZGVhZFBhdGhzKSB7XG4gICAgICBjb25zdCBjYWxsYmFjayA9IGZpbmlzaENicy5nZXQoZW50aXR5KVxuICAgICAgdW5yZWdpc3RlckVudGl0eShlbnRpdHkpXG4gICAgICBpZiAoY2FsbGJhY2spXG4gICAgICAgIGNhbGxiYWNrKClcbiAgICB9XG4gIH1cblxuICB0YXJnZXRFbmdpbmUuYWRkU3lzdGVtKHN5c3RlbSlcblxuICBmdW5jdGlvbiBzdGFydFBhdGgoXG4gICAgZW50aXR5OiBFbnRpdHksXG4gICAgcG9pbnRzOiBWZWN0b3IzW10sXG4gICAgZHVyYXRpb246IG51bWJlcixcbiAgICBmYWNlRGlyZWN0aW9uPzogYm9vbGVhbixcbiAgICBjdXJ2ZVNlZ21lbnRDb3VudD86IG51bWJlcixcbiAgICBvbkZpbmlzaENhbGxiYWNrPzogT25GaW5pc2hDYWxsYmFjayxcbiAgICBvblBvaW50UmVhY2hlZENhbGxiYWNrPzogT25Qb2ludFJlYWNoZWRDYWxsYmFja1xuICApIHtcbiAgICBpZiAocG9pbnRzLmxlbmd0aCA8IDIpXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0F0IGxlYXN0IDIgcG9pbnRzIGFyZSByZXF1aXJlZCB0byBmb3JtIGEgcGF0aC4nKVxuXG4gICAgaWYgKGR1cmF0aW9uID09IDApXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1BhdGggZHVyYXRpb24gbXVzdCBub3QgYmUgemVybycpXG5cbiAgICBpZiAoY3VydmVTZWdtZW50Q291bnQpIHtcbiAgICAgIGNvbnN0IGxvb3AgPSBWZWN0b3IzLmVxdWFscyhwb2ludHNbMF0sIHBvaW50c1twb2ludHMubGVuZ3RoIC0gMV0pXG4gICAgICBpZiAobG9vcCkge1xuICAgICAgICBwb2ludHMucG9wKClcbiAgICAgICAgcG9pbnRzLnVuc2hpZnQocG9pbnRzLnBvcCgpISlcbiAgICAgIH1cbiAgICAgIHBvaW50cyA9IGNyZWF0ZUNhdG11bGxSb21TcGxpbmUocG9pbnRzLCBjdXJ2ZVNlZ21lbnRDb3VudCwgbG9vcClcbiAgICB9IGVsc2Uge1xuICAgICAgY3VydmVTZWdtZW50Q291bnQgPSAxXG4gICAgfVxuXG4gICAgZmluaXNoQ2JzLnNldChlbnRpdHksIG9uRmluaXNoQ2FsbGJhY2spXG4gICAgcG9pbnRSZWFjaGVkQ2JzLnNldChlbnRpdHksIG9uUG9pbnRSZWFjaGVkQ2FsbGJhY2spXG5cbiAgICBsZXQgdG90YWxMZW5ndGggPSAwXG4gICAgY29uc3Qgc2VnbWVudExlbmd0aHMgPSBbXVxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcG9pbnRzLmxlbmd0aCAtIDE7IGkrKykge1xuICAgICAgbGV0IHNxRGlzdCA9IFZlY3RvcjMuZGlzdGFuY2UocG9pbnRzW2ldLCBwb2ludHNbaSArIDFdKVxuICAgICAgdG90YWxMZW5ndGggKz0gc3FEaXN0XG4gICAgICBzZWdtZW50TGVuZ3Rocy5wdXNoKHNxRGlzdClcbiAgICB9XG5cbiAgICBjb25zdCBzZWdtZW50VGltZXMgPSBbMF1cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNlZ21lbnRMZW5ndGhzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBzZWdtZW50VGltZXMucHVzaChzZWdtZW50TGVuZ3Roc1tpXSAvIHRvdGFsTGVuZ3RoICsgc2VnbWVudFRpbWVzW2ldKVxuICAgIH1cblxuICAgIEZvbGxvd1BhdGguY3JlYXRlT3JSZXBsYWNlKGVudGl0eSwge1xuICAgICAgcG9pbnRzOiBwb2ludHMsXG4gICAgICBzZWdtZW50VGltZXM6IHNlZ21lbnRUaW1lcyxcbiAgICAgIGN1cnZlU2VnbWVudENvdW50OiBjdXJ2ZVNlZ21lbnRDb3VudCxcbiAgICAgIHNwZWVkOiAxIC8gZHVyYXRpb24sXG4gICAgICBub3JtYWxpemVkVGltZTogMCxcbiAgICAgIGN1cnJlbnRJbmRleDogMCxcbiAgICAgIGZhY2VEaXJlY3Rpb246IGZhY2VEaXJlY3Rpb25cbiAgICB9KVxuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBzdGFydFN0cmFpZ2h0UGF0aChcbiAgICAgIGVudGl0eTogRW50aXR5LFxuICAgICAgcG9pbnRzOiBWZWN0b3IzW10sXG4gICAgICBkdXJhdGlvbjogbnVtYmVyLFxuICAgICAgZmFjZURpcmVjdGlvbj86IGJvb2xlYW4sXG4gICAgICBvbkZpbmlzaENhbGxiYWNrPzogT25GaW5pc2hDYWxsYmFjayxcbiAgICAgIG9uUG9pbnRSZWFjaGVkQ2FsbGJhY2s/OiBPblBvaW50UmVhY2hlZENhbGxiYWNrXG4gICAgKSB7XG4gICAgICByZXR1cm4gc3RhcnRQYXRoKGVudGl0eSwgcG9pbnRzLCBkdXJhdGlvbiwgZmFjZURpcmVjdGlvbiwgMCwgb25GaW5pc2hDYWxsYmFjaywgb25Qb2ludFJlYWNoZWRDYWxsYmFjaylcbiAgICB9LFxuICAgIHN0YXJ0U21vb3RoUGF0aChcbiAgICAgIGVudGl0eTogRW50aXR5LFxuICAgICAgcG9pbnRzOiBWZWN0b3IzW10sXG4gICAgICBkdXJhdGlvbjogbnVtYmVyLFxuICAgICAgc2VnbWVudENvdW50OiBudW1iZXIsXG4gICAgICBmYWNlRGlyZWN0aW9uPzogYm9vbGVhbixcbiAgICAgIG9uRmluaXNoQ2FsbGJhY2s/OiBPbkZpbmlzaENhbGxiYWNrLFxuICAgICAgb25Qb2ludFJlYWNoZWRDYWxsYmFjaz86IE9uUG9pbnRSZWFjaGVkQ2FsbGJhY2tcbiAgICApIHtcbiAgICAgIGlmIChzZWdtZW50Q291bnQgPCAyIHx8ICFOdW1iZXIuaXNJbnRlZ2VyKHNlZ21lbnRDb3VudCkpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgc2VnbWVudENvdW50IG11c3QgYmUgYW4gaW50ZWdlciB0aGF0IGlzIGdyZWF0ZXIgdGhhbiAyLCBnb3Q6ICR7c2VnbWVudENvdW50fWApXG4gICAgICByZXR1cm4gc3RhcnRQYXRoKGVudGl0eSwgcG9pbnRzLCBkdXJhdGlvbiwgZmFjZURpcmVjdGlvbiwgc2VnbWVudENvdW50LCBvbkZpbmlzaENhbGxiYWNrLCBvblBvaW50UmVhY2hlZENhbGxiYWNrKVxuICAgIH0sXG4gICAgc3RvcFBhdGgoZW50aXR5OiBFbnRpdHkpIHtcbiAgICAgIHVucmVnaXN0ZXJFbnRpdHkoZW50aXR5KVxuICAgIH0sXG4gICAgZ2V0T25GaW5pc2hDYWxsYmFjayhlbnRpdHk6IEVudGl0eSkge1xuICAgICAgaWYgKCFmaW5pc2hDYnMuaGFzKGVudGl0eSkpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRW50aXR5ICR7ZW50aXR5fSBpcyBub3QgcmVnaXN0ZXJlZCBpbiB0cmlnZ2VycyBzeXN0ZW1gKVxuICAgICAgcmV0dXJuIGZpbmlzaENicy5nZXQoZW50aXR5KVxuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgY29uc3QgcGF0aHMgPSBjcmVhdGVQYXRocyhlbmdpbmUpXG4iXX0=