UNPKG

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
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=