UNPKG

@dcl-sdk/utils

Version:

A collection of helpers to make it easier to build a Decentraland scene using the SDK 7.

126 lines 22.1 kB
import { engine, EntityState, Schemas, Transform } from '@dcl/sdk/ecs'; import { Scalar, Vector3, Quaternion } from '@dcl/sdk/math'; import { createCatmullRomSpline } from './math'; import { priority } from './priority'; 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, priority.PathSystemPriority); 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGF0aC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9wYXRoLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxNQUFNLEVBQVUsV0FBVyxFQUFXLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxjQUFjLENBQUE7QUFDdkYsT0FBTyxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFBO0FBQzNELE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLFFBQVEsQ0FBQTtBQUMvQyxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sWUFBWSxDQUFBO0FBT3JDLFNBQVMsV0FBVyxDQUFDLFlBQXFCO0lBQ3hDLE1BQU0sVUFBVSxHQUFHLFlBQVksQ0FBQyxlQUFlLENBQUMsc0JBQXNCLEVBQUU7UUFDdEUsTUFBTSxFQUFFLE9BQU8sQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQztRQUN0QyxhQUFhLEVBQUUsT0FBTyxDQUFDLE9BQU87UUFDOUIsS0FBSyxFQUFFLE9BQU8sQ0FBQyxNQUFNO1FBQ3JCLGNBQWMsRUFBRSxPQUFPLENBQUMsTUFBTTtRQUM5QixZQUFZLEVBQUUsT0FBTyxDQUFDLE1BQU07UUFDNUIsWUFBWSxFQUFFLE9BQU8sQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQztRQUMzQyxpQkFBaUIsRUFBRSxPQUFPLENBQUMsTUFBTTtLQUNsQyxDQUFDLENBQUE7SUFLRixNQUFNLFNBQVMsR0FBc0IsSUFBSSxHQUFHLEVBQUUsQ0FBQTtJQUM5QyxNQUFNLGVBQWUsR0FBOEIsSUFBSSxHQUFHLEVBQUUsQ0FBQTtJQUU1RCxTQUFTLGdCQUFnQixDQUFDLE1BQWM7UUFDdEMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQTtRQUN4QixlQUFlLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFBO1FBQzlCLFVBQVUsQ0FBQyxVQUFVLENBQUMsTUFB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LENBQUMsTUFBYztZQUNyQixnQkFBZ0IsQ0FBQyxNQUFNLENBQUMsQ0FBQTtRQUMxQixDQUFDO1FBQ0QsbUJBQW1CLENBQUMsTUFBYztZQUNoQyxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUM7Z0JBQ3hCLE1BQU0sSUFBSSxLQUFLLENBQUMsVUFBVSxNQUFNLHVDQUF1QyxDQUFDLENBQUE7WUFDMUUsT0FBTyxTQUFTLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFBO1FBQzlCLENBQUM7S0FDRixDQUFBO0FBQ0gsQ0FBQztBQUVELE1BQU0sQ0FBQyxNQUFNLEtBQUssR0FBRyxXQUFXLENBQUMsTUFBTSxDQUFDLENBQUEiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBlbmdpbmUsIEVudGl0eSwgRW50aXR5U3RhdGUsIElFbmdpbmUsIFNjaGVtYXMsIFRyYW5zZm9ybSB9IGZyb20gJ0BkY2wvc2RrL2VjcydcbmltcG9ydCB7IFNjYWxhciwgVmVjdG9yMywgUXVhdGVybmlvbiB9IGZyb20gJ0BkY2wvc2RrL21hdGgnXG5pbXBvcnQgeyBjcmVhdGVDYXRtdWxsUm9tU3BsaW5lIH0gZnJvbSAnLi9tYXRoJ1xuaW1wb3J0IHsgcHJpb3JpdHkgfSBmcm9tICcuL3ByaW9yaXR5J1xuXG5leHBvcnQgdHlwZSBQYXRocyA9IFJldHVyblR5cGU8dHlwZW9mIGNyZWF0ZVBhdGhzPlxuXG5leHBvcnQgdHlwZSBPbkZpbmlzaENhbGxiYWNrID0gKCkgPT4gdm9pZFxuZXhwb3J0IHR5cGUgT25Qb2ludFJlYWNoZWRDYWxsYmFjayA9IChwb2ludEluZGV4OiBudW1iZXIsIHBvaW50OiBWZWN0b3IzLCBuZXh0UG9pbnQ6IFZlY3RvcjMpID0+IHZvaWRcblxuZnVuY3Rpb24gY3JlYXRlUGF0aHModGFyZ2V0RW5naW5lOiBJRW5naW5lKSB7XG4gIGNvbnN0IEZvbGxvd1BhdGggPSB0YXJnZXRFbmdpbmUuZGVmaW5lQ29tcG9uZW50KCdkY2wudXRpbHMuRm9sbG93UGF0aCcsIHtcbiAgICBwb2ludHM6IFNjaGVtYXMuQXJyYXkoU2NoZW1hcy5WZWN0b3IzKSxcbiAgICBmYWNlRGlyZWN0aW9uOiBTY2hlbWFzLkJvb2xlYW4sXG4gICAgc3BlZWQ6IFNjaGVtYXMuTnVtYmVyLFxuICAgIG5vcm1hbGl6ZWRUaW1lOiBTY2hlbWFzLk51bWJlcixcbiAgICBjdXJyZW50SW5kZXg6IFNjaGVtYXMuTnVtYmVyLFxuICAgIHNlZ21lbnRUaW1lczogU2NoZW1hcy5BcnJheShTY2hlbWFzLk51bWJlciksXG4gICAgY3VydmVTZWdtZW50Q291bnQ6IFNjaGVtYXMuTnVtYmVyXG4gIH0pXG5cbiAgdHlwZSBGaW5pc2hDYWxsYmFja01hcCA9IE1hcDxFbnRpdHksIE9uRmluaXNoQ2FsbGJhY2sgfCB1bmRlZmluZWQ+XG4gIHR5cGUgT25Qb2ludFJlYWNoZWRDYWxsYmFja01hcCA9IE1hcDxFbnRpdHksIE9uUG9pbnRSZWFjaGVkQ2FsbGJhY2sgfCB1bmRlZmluZWQ+XG5cbiAgY29uc3QgZmluaXNoQ2JzOiBGaW5pc2hDYWxsYmFja01hcCA9IG5ldyBNYXAoKVxuICBjb25zdCBwb2ludFJlYWNoZWRDYnM6IE9uUG9pbnRSZWFjaGVkQ2FsbGJhY2tNYXAgPSBuZXcgTWFwKClcblxuICBmdW5jdGlvbiB1bnJlZ2lzdGVyRW50aXR5KGVudGl0eTogRW50aXR5KSB7XG4gICAgZmluaXNoQ2JzLmRlbGV0ZShlbnRpdHkpXG4gICAgcG9pbnRSZWFjaGVkQ2JzLmRlbGV0ZShlbnRpdHkpXG4gICAgRm9sbG93UGF0aC5kZWxldGVGcm9tKGVudGl0eSlcbiAgfVxuXG4gIGZ1bmN0aW9uIHN5c3RlbShkdDogbnVtYmVyKSB7XG4gICAgY29uc3QgZGVhZFBhdGhzID0gW11cbiAgICBjb25zdCBwb2ludFJlYWNoZWRQYXRocyA9IFtdXG5cbiAgICBmb3IgKGNvbnN0IGVudGl0eSBvZiBmaW5pc2hDYnMua2V5cygpKSB7XG4gICAgICBpZiAodGFyZ2V0RW5naW5lLmdldEVudGl0eVN0YXRlKGVudGl0eSkgPT0gRW50aXR5U3RhdGUuUmVtb3ZlZCB8fCAhRm9sbG93UGF0aC5oYXMoZW50aXR5KSkge1xuICAgICAgICB1bnJlZ2lzdGVyRW50aXR5KGVudGl0eSlcbiAgICAgICAgY29udGludWVcbiAgICAgIH1cblxuICAgICAgY29uc3QgdHJhbnNmb3JtID0gVHJhbnNmb3JtLmdldE11dGFibGUoZW50aXR5KVxuICAgICAgY29uc3QgcGF0aCA9IEZvbGxvd1BhdGguZ2V0TXV0YWJsZShlbnRpdHkpXG4gICAgICBwYXRoLm5vcm1hbGl6ZWRUaW1lID0gU2NhbGFyLmNsYW1wKHBhdGgubm9ybWFsaXplZFRpbWUgKyBkdCAqIHBhdGguc3BlZWQsIDAsIDEpXG4gICAgICBpZiAocGF0aC5ub3JtYWxpemVkVGltZSA+PSAxKVxuICAgICAgICBkZWFkUGF0aHMucHVzaChlbnRpdHkpXG5cbiAgICAgIHdoaWxlIChcbiAgICAgICAgcGF0aC5ub3JtYWxpemVkVGltZSA+PSBwYXRoLnNlZ21lbnRUaW1lc1twYXRoLmN1cnJlbnRJbmRleF0gJiZcbiAgICAgICAgcGF0aC5jdXJyZW50SW5kZXggPCBwYXRoLnBvaW50cy5sZW5ndGggLSAxXG4gICAgICApIHtcbiAgICAgICAgaWYgKHBhdGguZmFjZURpcmVjdGlvbikge1xuICAgICAgICAgIGNvbnN0IGRpcmVjdGlvbiA9IFZlY3RvcjMuc3VidHJhY3QocGF0aC5wb2ludHNbcGF0aC5jdXJyZW50SW5kZXggKyAxXSwgcGF0aC5wb2ludHNbcGF0aC5jdXJyZW50SW5kZXhdKVxuICAgICAgICAgIHRyYW5zZm9ybS5yb3RhdGlvbiA9IFF1YXRlcm5pb24ubG9va1JvdGF0aW9uKGRpcmVjdGlvbilcbiAgICAgICAgfVxuICAgICAgICBpZiAocGF0aC5jdXJyZW50SW5kZXggPiAwICYmIHBhdGguY3VycmVudEluZGV4ICUgcGF0aC5jdXJ2ZVNlZ21lbnRDb3VudCA9PSAwKSB7XG4gICAgICAgICAgY29uc3QgcG9pbnRJbmRleCA9IHBhdGguY3VycmVudEluZGV4IC8gcGF0aC5jdXJ2ZVNlZ21lbnRDb3VudFxuICAgICAgICAgIGNvbnN0IHBvaW50Q29vcmRzID0gcGF0aC5wb2ludHNbcGF0aC5jdXJyZW50SW5kZXhdXG4gICAgICAgICAgY29uc3QgbmV4dFBvaW50Q29vcmRzID0gcGF0aC5wb2ludHNbcGF0aC5jdXJyZW50SW5kZXggKyBwYXRoLmN1cnZlU2VnbWVudENvdW50XVxuICAgICAgICAgIHBvaW50UmVhY2hlZFBhdGhzLnB1c2goe2VudGl0eTogZW50aXR5LCBpbmRleDogcG9pbnRJbmRleCwgY29vcmRzOiBwb2ludENvb3JkcywgbmV4dENvb3JkczogbmV4dFBvaW50Q29vcmRzfSlcbiAgICAgICAgfVxuICAgICAgICBwYXRoLmN1cnJlbnRJbmRleCArPSAxXG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHRpbWVEaWZmID0gcGF0aC5zZWdtZW50VGltZXNbcGF0aC5jdXJyZW50SW5kZXhdIC0gcGF0aC5zZWdtZW50VGltZXNbcGF0aC5jdXJyZW50SW5kZXggLSAxXVxuICAgICAgY29uc3QgY29lZiA9IChwYXRoLnNlZ21lbnRUaW1lc1twYXRoLmN1cnJlbnRJbmRleF0gLSBwYXRoLm5vcm1hbGl6ZWRUaW1lKSAvIHRpbWVEaWZmXG4gICAgICB0cmFuc2Zvcm0ucG9zaXRpb24gPSBWZWN0b3IzLmxlcnAocGF0aC5wb2ludHNbcGF0aC5jdXJyZW50SW5kZXhdLCBwYXRoLnBvaW50c1twYXRoLmN1cnJlbnRJbmRleCAtIDFdLCBjb2VmKVxuICAgIH1cblxuICAgIGZvciAoY29uc3QgcG9pbnRSZWFjaGVkIG9mIHBvaW50UmVhY2hlZFBhdGhzKSB7XG4gICAgICBjb25zdCBjYWxsYmFjayA9IHBvaW50UmVhY2hlZENicy5nZXQocG9pbnRSZWFjaGVkLmVudGl0eSlcbiAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICBjYWxsYmFjayhwb2ludFJlYWNoZWQuaW5kZXgsIHBvaW50UmVhY2hlZC5jb29yZHMsIHBvaW50UmVhY2hlZC5uZXh0Q29vcmRzKVxuICAgICAgfVxuICAgIH1cblxuICAgIGZvciAoY29uc3QgZW50aXR5IG9mIGRlYWRQYXRocykge1xuICAgICAgY29uc3QgY2FsbGJhY2sgPSBmaW5pc2hDYnMuZ2V0KGVudGl0eSlcbiAgICAgIHVucmVnaXN0ZXJFbnRpdHkoZW50aXR5KVxuICAgICAgaWYgKGNhbGxiYWNrKVxuICAgICAgICBjYWxsYmFjaygpXG4gICAgfVxuICB9XG5cbiAgdGFyZ2V0RW5naW5lLmFkZFN5c3RlbShzeXN0ZW0sIHByaW9yaXR5LlBhdGhTeXN0ZW1Qcmlvcml0eSlcblxuICBmdW5jdGlvbiBzdGFydFBhdGgoXG4gICAgZW50aXR5OiBFbnRpdHksXG4gICAgcG9pbnRzOiBWZWN0b3IzW10sXG4gICAgZHVyYXRpb246IG51bWJlcixcbiAgICBmYWNlRGlyZWN0aW9uPzogYm9vbGVhbixcbiAgICBjdXJ2ZVNlZ21lbnRDb3VudD86IG51bWJlcixcbiAgICBvbkZpbmlzaENhbGxiYWNrPzogT25GaW5pc2hDYWxsYmFjayxcbiAgICBvblBvaW50UmVhY2hlZENhbGxiYWNrPzogT25Qb2ludFJlYWNoZWRDYWxsYmFja1xuICApIHtcbiAgICBpZiAocG9pbnRzLmxlbmd0aCA8IDIpXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0F0IGxlYXN0IDIgcG9pbnRzIGFyZSByZXF1aXJlZCB0byBmb3JtIGEgcGF0aC4nKVxuXG4gICAgaWYgKGR1cmF0aW9uID09IDApXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1BhdGggZHVyYXRpb24gbXVzdCBub3QgYmUgemVybycpXG5cbiAgICBpZiAoY3VydmVTZWdtZW50Q291bnQpIHtcbiAgICAgIGNvbnN0IGxvb3AgPSBWZWN0b3IzLmVxdWFscyhwb2ludHNbMF0sIHBvaW50c1twb2ludHMubGVuZ3RoIC0gMV0pXG4gICAgICBpZiAobG9vcCkge1xuICAgICAgICBwb2ludHMucG9wKClcbiAgICAgICAgcG9pbnRzLnVuc2hpZnQocG9pbnRzLnBvcCgpISlcbiAgICAgIH1cbiAgICAgIHBvaW50cyA9IGNyZWF0ZUNhdG11bGxSb21TcGxpbmUocG9pbnRzLCBjdXJ2ZVNlZ21lbnRDb3VudCwgbG9vcClcbiAgICB9IGVsc2Uge1xuICAgICAgY3VydmVTZWdtZW50Q291bnQgPSAxXG4gICAgfVxuXG4gICAgZmluaXNoQ2JzLnNldChlbnRpdHksIG9uRmluaXNoQ2FsbGJhY2spXG4gICAgcG9pbnRSZWFjaGVkQ2JzLnNldChlbnRpdHksIG9uUG9pbnRSZWFjaGVkQ2FsbGJhY2spXG5cbiAgICBsZXQgdG90YWxMZW5ndGggPSAwXG4gICAgY29uc3Qgc2VnbWVudExlbmd0aHMgPSBbXVxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcG9pbnRzLmxlbmd0aCAtIDE7IGkrKykge1xuICAgICAgbGV0IHNxRGlzdCA9IFZlY3RvcjMuZGlzdGFuY2UocG9pbnRzW2ldLCBwb2ludHNbaSArIDFdKVxuICAgICAgdG90YWxMZW5ndGggKz0gc3FEaXN0XG4gICAgICBzZWdtZW50TGVuZ3Rocy5wdXNoKHNxRGlzdClcbiAgICB9XG5cbiAgICBjb25zdCBzZWdtZW50VGltZXMgPSBbMF1cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNlZ21lbnRMZW5ndGhzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBzZWdtZW50VGltZXMucHVzaChzZWdtZW50TGVuZ3Roc1tpXSAvIHRvdGFsTGVuZ3RoICsgc2VnbWVudFRpbWVzW2ldKVxuICAgIH1cblxuICAgIEZvbGxvd1BhdGguY3JlYXRlT3JSZXBsYWNlKGVudGl0eSwge1xuICAgICAgcG9pbnRzOiBwb2ludHMsXG4gICAgICBzZWdtZW50VGltZXM6IHNlZ21lbnRUaW1lcyxcbiAgICAgIGN1cnZlU2VnbWVudENvdW50OiBjdXJ2ZVNlZ21lbnRDb3VudCxcbiAgICAgIHNwZWVkOiAxIC8gZHVyYXRpb24sXG4gICAgICBub3JtYWxpemVkVGltZTogMCxcbiAgICAgIGN1cnJlbnRJbmRleDogMCxcbiAgICAgIGZhY2VEaXJlY3Rpb246IGZhY2VEaXJlY3Rpb25cbiAgICB9KVxuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBzdGFydFN0cmFpZ2h0UGF0aChcbiAgICAgIGVudGl0eTogRW50aXR5LFxuICAgICAgcG9pbnRzOiBWZWN0b3IzW10sXG4gICAgICBkdXJhdGlvbjogbnVtYmVyLFxuICAgICAgZmFjZURpcmVjdGlvbj86IGJvb2xlYW4sXG4gICAgICBvbkZpbmlzaENhbGxiYWNrPzogT25GaW5pc2hDYWxsYmFjayxcbiAgICAgIG9uUG9pbnRSZWFjaGVkQ2FsbGJhY2s/OiBPblBvaW50UmVhY2hlZENhbGxiYWNrXG4gICAgKSB7XG4gICAgICByZXR1cm4gc3RhcnRQYXRoKGVudGl0eSwgcG9pbnRzLCBkdXJhdGlvbiwgZmFjZURpcmVjdGlvbiwgMCwgb25GaW5pc2hDYWxsYmFjaywgb25Qb2ludFJlYWNoZWRDYWxsYmFjaylcbiAgICB9LFxuICAgIHN0YXJ0U21vb3RoUGF0aChcbiAgICAgIGVudGl0eTogRW50aXR5LFxuICAgICAgcG9pbnRzOiBWZWN0b3IzW10sXG4gICAgICBkdXJhdGlvbjogbnVtYmVyLFxuICAgICAgc2VnbWVudENvdW50OiBudW1iZXIsXG4gICAgICBmYWNlRGlyZWN0aW9uPzogYm9vbGVhbixcbiAgICAgIG9uRmluaXNoQ2FsbGJhY2s/OiBPbkZpbmlzaENhbGxiYWNrLFxuICAgICAgb25Qb2ludFJlYWNoZWRDYWxsYmFjaz86IE9uUG9pbnRSZWFjaGVkQ2FsbGJhY2tcbiAgICApIHtcbiAgICAgIGlmIChzZWdtZW50Q291bnQgPCAyIHx8ICFOdW1iZXIuaXNJbnRlZ2VyKHNlZ21lbnRDb3VudCkpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgc2VnbWVudENvdW50IG11c3QgYmUgYW4gaW50ZWdlciB0aGF0IGlzIGdyZWF0ZXIgdGhhbiAyLCBnb3Q6ICR7c2VnbWVudENvdW50fWApXG4gICAgICByZXR1cm4gc3RhcnRQYXRoKGVudGl0eSwgcG9pbnRzLCBkdXJhdGlvbiwgZmFjZURpcmVjdGlvbiwgc2VnbWVudENvdW50LCBvbkZpbmlzaENhbGxiYWNrLCBvblBvaW50UmVhY2hlZENhbGxiYWNrKVxuICAgIH0sXG4gICAgc3RvcFBhdGgoZW50aXR5OiBFbnRpdHkpIHtcbiAgICAgIHVucmVnaXN0ZXJFbnRpdHkoZW50aXR5KVxuICAgIH0sXG4gICAgZ2V0T25GaW5pc2hDYWxsYmFjayhlbnRpdHk6IEVudGl0eSkge1xuICAgICAgaWYgKCFmaW5pc2hDYnMuaGFzKGVudGl0eSkpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRW50aXR5ICR7ZW50aXR5fSBpcyBub3QgcmVnaXN0ZXJlZCBpbiB0cmlnZ2VycyBzeXN0ZW1gKVxuICAgICAgcmV0dXJuIGZpbmlzaENicy5nZXQoZW50aXR5KVxuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgY29uc3QgcGF0aHMgPSBjcmVhdGVQYXRocyhlbmdpbmUpXG4iXX0=