diff --git a/skycraft/index.html b/skycraft/index.html new file mode 100644 index 0000000..48cf3c1 --- /dev/null +++ b/skycraft/index.html @@ -0,0 +1,93 @@ + + + + WebMinecraft + + + + + + + +
+ +
+ +
+
+

Light

+

Direction

+

+ x: + +

+

+ y: + +

+

+ z: + +

+

+

+

+

Ambiant light amount

+

+ +

+

Sky color

+

+ r: + +

+

+ g: + +

+

+ b: + +

+

+

+
+
+

Physics

+

+ Gravity: +

+

+ Jump force: +

+
+
+
+ + + \ No newline at end of file diff --git a/skycraft/index.js b/skycraft/index.js new file mode 100644 index 0000000..2e83be0 --- /dev/null +++ b/skycraft/index.js @@ -0,0 +1,695 @@ +//import { initUiListeners, setupParamPanel, tick } from './game'; +//import { initWorldGl, makeWorld } from './world'; +import * as se3 from '../se3'; +import {loadTexture, makeProgram} from '../gl'; +import {makeFace, makeBufferFromFaces} from '../geometry'; + +const VSHADER = ` +attribute vec3 aPosition; +attribute vec3 aNormal; +attribute vec2 aTextureCoord; + +uniform mat4 uProjection; +uniform mat4 uModel; +uniform mat4 uView; +uniform vec3 uLightDirection; +uniform float uAmbiantLight; + +varying highp vec2 vTextureCoord; +varying lowp vec3 vLighting; +varying lowp float vDistance; + +void main() { + highp mat4 modelview = uView * uModel; + + gl_Position = uProjection * modelview * vec4(aPosition, 1.0); + + lowp vec3 normal = mat3(uModel) * aNormal; + lowp float diffuseAmount = max(dot(-uLightDirection, normal), 0.0); + lowp vec3 ambiant = uAmbiantLight * vec3(1.0, 1.0, 0.9); + vLighting = ambiant + vec3(1.0, 1.0, 1.0) * diffuseAmount; + + vTextureCoord = aTextureCoord; + + vDistance = length(modelview * vec4(aPosition, 1.0)); +} +`; + +const FSHADER = ` +uniform sampler2D uSampler; +uniform lowp vec3 uFogColor; + +varying highp vec2 vTextureCoord; +varying lowp vec3 vLighting; +varying lowp float vDistance; + +void main() { + highp vec4 color = texture2D(uSampler, vTextureCoord); + if (color.a < 0.1) { + discard; + } + lowp float fogamount = smoothstep(80.0, 100.0, vDistance); + gl_FragColor = mix(vec4(vLighting * color.rgb, color.a), vec4(uFogColor, 1.0), fogamount); +} +`; + +const kEpoch = 0; + +async function initWorldGl(gl) { + const program = makeProgram(gl, VSHADER, FSHADER); + const texture = await loadTexture(gl, 'texture.png'); + + // load those ahead of time + const viewLoc = gl.getUniformLocation(program, 'uView'); + const modelLoc = gl.getUniformLocation(program, 'uModel'); + const projLoc = gl.getUniformLocation(program, 'uProjection'); + const samplerLoc = gl.getUniformLocation(program, 'uSampler'); + const fogColorLoc = gl.getUniformLocation(program, 'uFogColor'); + const lightDirectionLoc = gl.getUniformLocation(program, 'uLightDirection'); + const ambiantLoc = gl.getUniformLocation(program, 'uAmbiantLight'); + + const positionLoc = gl.getAttribLocation(program, 'aPosition'); + const normalLoc = gl.getAttribLocation(program, 'aNormal'); + const textureLoc = gl.getAttribLocation(program, 'aTextureCoord'); + + const setupScene = (sceneParams) => { + const { + projectionMatrix, + viewMatrix, + fogColor, + lightDirection, + ambiantLightAmount, + } = sceneParams; + + gl.useProgram(program); + + gl.uniformMatrix4fv(projLoc, false, new Float32Array(projectionMatrix)); + gl.uniformMatrix4fv(viewLoc, false, new Float32Array(viewMatrix)); + gl.uniform3fv(fogColorLoc, fogColor); + gl.uniform3fv(lightDirectionLoc, lightDirection); + gl.uniform1f(ambiantLoc, ambiantLightAmount); + + // doing this here because it's the same for all world stuff + gl.uniformMatrix4fv(modelLoc, false, new Float32Array(se3.identity())); + gl.uniform1i(samplerLoc, 0); + + gl.enableVertexAttribArray(positionLoc); + gl.enableVertexAttribArray(normalLoc); + gl.enableVertexAttribArray(textureLoc); + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_2D, texture); + }; + + const drawObject = (objectParams) => { + const { + position, + orientation, + glBuffer, + numVertices, + } = objectParams; + + gl.uniformMatrix4fv(modelLoc, false, new Float32Array(se3.product( + se3.translation(...position), orientation))); + + gl.bindBuffer(gl.ARRAY_BUFFER, glBuffer); + + gl.vertexAttribPointer(positionLoc, 3, gl.FLOAT, false, 20, 0); + gl.vertexAttribPointer(normalLoc, 3, gl.BYTE, true, 20, 12); + gl.vertexAttribPointer(textureLoc, 2, gl.UNSIGNED_SHORT, true, 20, 16); + + gl.drawArrays(gl.TRIANGLES, 0, numVertices); + }; + + return { + setupScene, + drawObject, + }; +} + +const ORBIT_VSHADER = ` +attribute vec3 aPosition; +attribute vec2 aValue; + +uniform mat4 uProjection; +uniform mat4 uModel; +uniform mat4 uView; + +varying lowp vec2 vCoords; + +void main() { + highp mat4 modelview = uView * uModel; + gl_Position = uProjection * modelview * vec4(aPosition, 1.0); + + vCoords = aValue; +} +`; + +const ORBIT_FSHADER = ` +varying lowp vec2 vCoords; + +void main() { + lowp float x = vCoords.x; + lowp float y = vCoords.y; + + lowp float f = sqrt(x * x + y * y); + + if (f > 1.00) { + discard; + } else if (f < 0.98) { + discard; + } + gl_FragColor = vec4(1, .5, 0, 1); +} +`; + +function getOrbitDrawContext(gl) { + const program = makeProgram(gl, ORBIT_VSHADER, ORBIT_FSHADER); + + // load those ahead of time + const viewLoc = gl.getUniformLocation(program, 'uView'); + const modelLoc = gl.getUniformLocation(program, 'uModel'); + const projLoc = gl.getUniformLocation(program, 'uProjection'); + + const positionLoc = gl.getAttribLocation(program, 'aPosition'); + const valueLoc = gl.getAttribLocation(program, 'aValue'); + + const setupScene = (sceneParams) => { + const { + projectionMatrix, + viewMatrix, + } = sceneParams; + + gl.useProgram(program); + + gl.uniformMatrix4fv(projLoc, false, new Float32Array(projectionMatrix)); + gl.uniformMatrix4fv(viewLoc, false, new Float32Array(viewMatrix)); + + // doing this here because it's the same for all world stuff + gl.uniformMatrix4fv(modelLoc, false, new Float32Array(se3.identity())); + + gl.enableVertexAttribArray(positionLoc); + gl.enableVertexAttribArray(valueLoc); + }; + + const drawObject = (objectParams) => { + const { + position, + orientation, + value, + glBuffer, + } = objectParams; + + gl.uniformMatrix4fv(modelLoc, false, new Float32Array(se3.product( + se3.translation(...position), orientation))); + + gl.bindBuffer(gl.ARRAY_BUFFER, glBuffer); + + gl.vertexAttribPointer(positionLoc, 3, gl.FLOAT, false, 20, 0); + gl.vertexAttribPointer(valueLoc, 2, gl.FLOAT, false, 20, 12); + + gl.disable(gl.CULL_FACE); + gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); + gl.enable(gl.CULL_FACE); + }; + + return { + setupScene, + drawObject, + }; +} + +function initUiListeners(canvas, context) { + const canvasClickHandler = () => { + canvas.requestPointerLock(); + canvas.onclick = null; +// const clickListener = e => { +// switch(e.button) { +// case 0: // left click +// destroySelectedBlock(context); +// break; +// case 2: // right click +// makeDirBlock(context); +// break; +// } +// }; + const clickListener = e => {}; + const keyListener = e => { + if (e.type === 'keydown') { + if (e.repeat) return; + context.keys.add(e.code); + + switch (e.code) { + case 'KeyF': +// context.flying = !context.flying; + return false; + case 'Space': + if (!context.flying) { + if (context.jumpAmount > 0) { + const amount = context.jumpForce; + context.camera.velocity[1] = amount; + context.jumpAmount -= 1; + } + } + return false; + } + } else { + context.keys.delete(e.code); + } + }; + const moveListener = e => { + context.camera.orientation[1] -= e.movementX / 500; + context.camera.orientation[0] -= e.movementY / 500; + + context.camera.orientation[0] = Math.min(Math.max( + context.camera.orientation[0], -Math.PI / 2 + ), Math.PI / 2); + }; + const changeListener = () => { + if (document.pointerLockElement === canvas) { + return; + } + document.removeEventListener('pointerdown', clickListener); + document.removeEventListener('pointerlockchange', changeListener); + document.removeEventListener('pointermove', moveListener); + document.removeEventListener('keydown', keyListener); + document.removeEventListener('keyup', keyListener); + canvas.onclick = canvasClickHandler; + }; + document.addEventListener('pointerdown', clickListener); + document.addEventListener('pointerlockchange', changeListener); + document.addEventListener('pointermove', moveListener); + document.addEventListener('keydown', keyListener); + document.addEventListener('keyup', keyListener); + }; + canvas.onclick = canvasClickHandler; + document.addEventListener('keydown', e => { + if (e.repeat) return; + switch (e.code) { + case 'F11': + canvas.requestFullscreen(); + break; + } + }); +} + +function handleInput(context) { + const move = (forward, right) => { + const dir = [right, 0, -forward, 1.0]; + const ori = se3.roty(context.camera.orientation[1]); + const tf = se3.apply(ori, dir); + const maxSpeed = 8; + const airMovement = 0.08; + + if (context.flying) { + context.camera.position[0] += tf[0] / 60; + context.camera.position[2] += tf[2] / 60; + } + if (context.isOnGround) { + context.camera.velocity[0] = tf[0]; + context.camera.velocity[2] = tf[2]; + } else { + const vel = context.camera.velocity; + + vel[0] += tf[0] * airMovement; + vel[2] += tf[2] * airMovement; + + const curVel = Math.sqrt(vel[0] * vel[0] + vel[2] * vel[2]); + + if (curVel > maxSpeed) { + vel[0] *= maxSpeed / curVel; + vel[2] *= maxSpeed / curVel; + } + } + }; + + context.keys.forEach(key => { + switch (key) { + case 'KeyW': + move(8, 0.0); + return; + case 'KeyA': + move(0.0, -8); + return; + case 'KeyS': + move(-8, 0.0); + return; + case 'KeyD': + move(0.0, 8); + return; + + case 'Space': + if (context.flying) { + context.camera.position[1] += 8 / 60; + } + return; + + case 'ShiftLeft': + context.camera.position[1] -= 8 / 60; + return; + } + }); +} + +function updatePhysics(time, context) { +} + +function updateGeometry(context, timeout_ms = 10) { +} + +function normalizeAngle(theta) { + const twopi = 2 * Math.PI; + return theta - twopi * Math.floor((theta + twopi) / twopi); +} + +/** Let's be honest I should clean this up. + * Right now it mostly only works with elliptical orbits (e < 1), + * which is fine for planets & stuff, but not for my spacecraft (or comets) + * + * This is the part that solves Kepler's equation using Newton's method. + * For circular-ish orbits, one or two iterations are usually enough. + * More excentric orbits can take more (6 or 7?). + */ +function getCartesianPosition(orbit, mu, time) { + const { + excentricity: e, + semimajorAxis: a, + inclination: i, + ascendingNodeLongitude: Om, + periapsisArgument: w, + } = orbit; + const n = Math.sqrt(mu/(a**3)); // mean motion + const M = n * time; // mean anomaly +// const nu = ( +// M +// + (2 * e - e**3 / 4) * Math.sin(M) +// + 5/4 * e**2 * Math.sin(2*M) +// + 13/12 * e**3 * Math.sin(3*M) +// ); // true anomaly, doesn't work :( + + // Newton's method + var E2; + var E = M; + for (var j = 1; j < 20; ++j) { + if (e < 0.001) { + break; + } + if (e < 1) { + E2 = E - (E - e * Math.sin(E) - M) / (1 - e * Math.cos(E)); + } else if (e > 1) { + E2 = E - (-E + e * sinh(E) - M) / (e * cosh(E) - 1); + } else { + E2 = E - (E + E*E*E/3 - M) / (1 + E*E); + } + if (Math.abs(E - E2) < 1e-10) { + break; + } + E = E2; + } + const nu = 2 * Math.atan(Math.sqrt((1+e) / (1-e)) * Math.tan(E/2)); + const r = a * (1 - e**2) / (1 + e * Math.cos(nu)); + + const cOm = Math.cos(Om); + const sOm = Math.sin(Om); + const cwnu = Math.cos(w + nu); + const swnu = Math.sin(w + nu); + + const x = r * Math.cos(i) * (cOm * cwnu - sOm * swnu); + const y = r * (sOm * cwnu + cOm * swnu); + const z = r * Math.sin(i) * cwnu; + + return [x, y, z]; +} + +function getOrientation(body, time) { + return se3.rotxyz( + body.spin[0] * time, + body.spin[1] * time, + body.spin[2] * time, + ); +} + +function makeOrbitObject(context, orbit, parentPosition) { + const {gl} = context; + const position = parentPosition; + const glContext = context.orbitGlContext; + const orientation = [ + se3.rotz(orbit.ascendingNodeLongitude), + se3.roty(-orbit.inclination), + se3.rotz(orbit.periapsisArgument), + ].reduce(se3.product); + + const buffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, buffer); + + const a = orbit.semimajorAxis; + const b = a * Math.sqrt(1 - orbit.excentricity**2); + + const x = - orbit.semimajorAxis * orbit.excentricity; + + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ + x-a, -b, 0, -1, -1, + x-a, +b, 0, -1, +1, + x+a, -b, 0, +1, -1, + x+a, +b, 0, +1, +1, + ]), gl.STATIC_DRAW); + + const geometry = { + glBuffer: buffer, + numVertices: 4, + delete: () => gl.deleteBuffer(buffer), + }; + + return { + geometry, + orientation, + position, + glContext, + }; +} + +function getObjects(context, body, time, parentBody, parentPosition) { + const kGravitationalConstant = 6.674e-11; + const objects = []; + const {gl, glContext} = context; + let position = [0, 0, 0]; + if (parentBody !== undefined) { +// const mu = kGravitationalConstant * parentBody.mass; + const mu = 10; + const coord = getCartesianPosition(body.orbit, mu, time); + position = [ + parentPosition[0] + coord[0], + parentPosition[1] + coord[1], + parentPosition[2] + coord[2], + ]; + + objects.push(makeOrbitObject(context, body.orbit, parentPosition)); + } + + objects.push({ + geometry: makeBufferFromFaces(gl, body.geometry), + orientation: getOrientation(body, time), + position, + glContext, + }); + + if (body.children !== undefined) { + for (const child of body.children) { + objects.push(...getObjects(context, child, time, body, position)); + } + } + + return objects; +} + +function draw(context, time) { + const {gl, camera, universe} = context; + const objects = getObjects(context, universe, time * 0.001); + + gl.clearColor(...context.skyColor, 1.0); + gl.clearDepth(1.0); + gl.enable(gl.DEPTH_TEST); + gl.depthFunc(gl.LEQUAL); + + gl.enable(gl.CULL_FACE); + gl.cullFace(gl.BACK); + gl.enable(gl.BLEND); + gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); + + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + + const camrot = camera.orientation; + const campos = camera.position; + const viewMatrix = se3.product( + se3.rotxyz(-camrot[0], -camrot[1], -camrot[2]), + se3.translation(-campos[0], -campos[1], -campos[2]) + ); + + let lastGlContext; + + for (const {position, orientation, geometry, glContext} of objects) { + if (glContext !== lastGlContext) { + glContext.setupScene({ + projectionMatrix: context.projMatrix, + viewMatrix, + fogColor: context.skyColor, + lightDirection: context.lightDirection, + ambiantLightAmount: context.ambiantLight, + }); + } + + lastGlContext = glContext; + + glContext.drawObject({ + position, + orientation, + glBuffer: geometry.glBuffer, + numVertices: geometry.numVertices, + }); + } +} + +function tick(time, context) { + handleInput(context); + updatePhysics(time, context); + + const campos = context.camera.position; + + // world generation / geometry update + { + // frame time is typically 16.7ms, so this may lag a bit + let timeLeft = 10; + const start = performance.now(); + updateGeometry(context, timeLeft); + } + + draw(context, time); + + const dt = (time - context.lastFrameTime) * 0.001; + context.lastFrameTime = time; + + document.querySelector('#fps').textContent = `${1.0 / dt} fps`; + + requestAnimationFrame(time => tick(time, context)); +} + +function makeCube(texture) { + return [ + makeFace('-x', texture, [-0.5, 0, 0]), + makeFace('+x', texture, [+0.5, 0, 0]), + makeFace('-y', texture, [0, -0.5, 0]), + makeFace('+y', texture, [0, +0.5, 0]), + makeFace('-z', texture, [0, 0, -0.5]), + makeFace('+z', texture, [0, 0, +0.5]), + ]; +} + +function makeObjects(gl) { + const texture = [0, 4]; + const faces = [ + makeFace('-x', texture, [-0.5, 0, 0]), + makeFace('+x', texture, [+0.5, 0, 0]), + makeFace('-y', texture, [0, -0.5, 0]), + makeFace('+y', texture, [0, +0.5, 0]), + makeFace('-z', texture, [0, 0, -0.5]), + makeFace('+z', texture, [0, 0, +0.5]), + ]; + return [ + { + geometry: makeBufferFromFaces(gl, faces), + orientation: [0, 0, 0], + position: [0, 0, 0], + }, + ]; +} + +function makeSolarSystem(gl) { + return { + mass: 1.0, + spin: [0, 1.0, 0], + geometry: makeCube([0, 4]), + children: [ + { + mass: 0.1, + spin: [0.2, 0.0, 0.0], + geometry: makeCube([0, 8]), + orbit: { + excentricity: 0, + semimajorAxis: 3, + inclination: 0, + ascendingNodeLongitude: 0, + periapsisArgument: 0, + trueAnomaly: 0, + }, + }, + { + mass: 0.1, + spin: [0.2, 0.0, 0.0], + geometry: makeCube([0, 1]), + orbit: { + excentricity: 0.8, + semimajorAxis: 5, + inclination: 0, + ascendingNodeLongitude: 0, + periapsisArgument: 0, + trueAnomaly: 0, + }, + }, + { + mass: 0.1, + spin: [0.0, 0.0, 1.0], + geometry: makeCube([9, 9]), + orbit: { + excentricity: 0.3, + semimajorAxis: 5, + inclination: 1.0, + ascendingNodeLongitude: 0, + periapsisArgument: 0, + trueAnomaly: 0, + }, + }, + ], + } +} + +async function main() { + const canvas = document.querySelector('#game'); + // adjust canvas aspect ratio to that of the screen + canvas.height = screen.height / screen.width * canvas.width; + const gl = canvas.getContext('webgl'); + + if (gl === null) { + console.error('webgl not available') + return; + } + + const context = { + gl, + projMatrix: se3.perspective(Math.PI / 3, canvas.clientWidth / canvas.clientHeight, 0.1, 100.0), + camera: { + position: [0.0, 0.0, 2.0], + orientation: [0.0, 0.0, 0.0], + velocity: [0, 0, 0], + }, + keys: new Set(), + lightDirection: [-0.2, -0.5, 0.4], + skyColor: [0.10, 0.15, 0.2], + ambiantLight: 0.7, + blockSelectDistance: 8, + flying: true, + isOnGround: false, + gravity: -17, + jumpForce: 6.5, +// objects: makeObjects(gl), + universe: makeSolarSystem(gl), + }; + + context.glContext = await initWorldGl(gl); + context.orbitGlContext = getOrbitDrawContext(gl); + initUiListeners(canvas, context); + +// setupParamPanel(context); + + requestAnimationFrame(time => tick(time, context)); +} + +window.onload = main; diff --git a/skycraft/package.json b/skycraft/package.json new file mode 100644 index 0000000..7325199 --- /dev/null +++ b/skycraft/package.json @@ -0,0 +1,14 @@ +{ + "name": "skycraft", + "version": "1.0.0", + "main": "index.js", + "license": "MIT", + "dependencies": { + "esbuild": "^0.14.2" + }, + "scripts": { + "watch": "esbuild --outfile=app.js index.js --bundle --sourcemap=inline --watch", + "serve": "esbuild --outfile=app.js index.js --bundle --sourcemap=inline --servedir=.", + "build": "esbuild --outfile=app.js index.js --bundle --minify" + } +} diff --git a/skycraft/texture.png b/skycraft/texture.png new file mode 120000 index 0000000..71e5e58 --- /dev/null +++ b/skycraft/texture.png @@ -0,0 +1 @@ +../texture.png \ No newline at end of file diff --git a/skycraft/yarn.lock b/skycraft/yarn.lock new file mode 100644 index 0000000..646c141 --- /dev/null +++ b/skycraft/yarn.lock @@ -0,0 +1,135 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@esbuild/linux-loong64@0.14.54": + version "0.14.54" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.14.54.tgz#de2a4be678bd4d0d1ffbb86e6de779cde5999028" + integrity sha512-bZBrLAIX1kpWelV0XemxBZllyRmM6vgFQQG2GdNb+r3Fkp0FOh1NJSvekXDs7jq70k4euu1cryLMfU+mTXlEpw== + +esbuild-android-64@0.14.54: + version "0.14.54" + resolved "https://registry.yarnpkg.com/esbuild-android-64/-/esbuild-android-64-0.14.54.tgz#505f41832884313bbaffb27704b8bcaa2d8616be" + integrity sha512-Tz2++Aqqz0rJ7kYBfz+iqyE3QMycD4vk7LBRyWaAVFgFtQ/O8EJOnVmTOiDWYZ/uYzB4kvP+bqejYdVKzE5lAQ== + +esbuild-android-arm64@0.14.54: + version "0.14.54" + resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.54.tgz#8ce69d7caba49646e009968fe5754a21a9871771" + integrity sha512-F9E+/QDi9sSkLaClO8SOV6etqPd+5DgJje1F9lOWoNncDdOBL2YF59IhsWATSt0TLZbYCf3pNlTHvVV5VfHdvg== + +esbuild-darwin-64@0.14.54: + version "0.14.54" + resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.54.tgz#24ba67b9a8cb890a3c08d9018f887cc221cdda25" + integrity sha512-jtdKWV3nBviOd5v4hOpkVmpxsBy90CGzebpbO9beiqUYVMBtSc0AL9zGftFuBon7PNDcdvNCEuQqw2x0wP9yug== + +esbuild-darwin-arm64@0.14.54: + version "0.14.54" + resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.54.tgz#3f7cdb78888ee05e488d250a2bdaab1fa671bf73" + integrity sha512-OPafJHD2oUPyvJMrsCvDGkRrVCar5aVyHfWGQzY1dWnzErjrDuSETxwA2HSsyg2jORLY8yBfzc1MIpUkXlctmw== + +esbuild-freebsd-64@0.14.54: + version "0.14.54" + resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.54.tgz#09250f997a56ed4650f3e1979c905ffc40bbe94d" + integrity sha512-OKwd4gmwHqOTp4mOGZKe/XUlbDJ4Q9TjX0hMPIDBUWWu/kwhBAudJdBoxnjNf9ocIB6GN6CPowYpR/hRCbSYAg== + +esbuild-freebsd-arm64@0.14.54: + version "0.14.54" + resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.54.tgz#bafb46ed04fc5f97cbdb016d86947a79579f8e48" + integrity sha512-sFwueGr7OvIFiQT6WeG0jRLjkjdqWWSrfbVwZp8iMP+8UHEHRBvlaxL6IuKNDwAozNUmbb8nIMXa7oAOARGs1Q== + +esbuild-linux-32@0.14.54: + version "0.14.54" + resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.14.54.tgz#e2a8c4a8efdc355405325033fcebeb941f781fe5" + integrity sha512-1ZuY+JDI//WmklKlBgJnglpUL1owm2OX+8E1syCD6UAxcMM/XoWd76OHSjl/0MR0LisSAXDqgjT3uJqT67O3qw== + +esbuild-linux-64@0.14.54: + version "0.14.54" + resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.14.54.tgz#de5fdba1c95666cf72369f52b40b03be71226652" + integrity sha512-EgjAgH5HwTbtNsTqQOXWApBaPVdDn7XcK+/PtJwZLT1UmpLoznPd8c5CxqsH2dQK3j05YsB3L17T8vE7cp4cCg== + +esbuild-linux-arm64@0.14.54: + version "0.14.54" + resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.54.tgz#dae4cd42ae9787468b6a5c158da4c84e83b0ce8b" + integrity sha512-WL71L+0Rwv+Gv/HTmxTEmpv0UgmxYa5ftZILVi2QmZBgX3q7+tDeOQNqGtdXSdsL8TQi1vIaVFHUPDe0O0kdig== + +esbuild-linux-arm@0.14.54: + version "0.14.54" + resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.54.tgz#a2c1dff6d0f21dbe8fc6998a122675533ddfcd59" + integrity sha512-qqz/SjemQhVMTnvcLGoLOdFpCYbz4v4fUo+TfsWG+1aOu70/80RV6bgNpR2JCrppV2moUQkww+6bWxXRL9YMGw== + +esbuild-linux-mips64le@0.14.54: + version "0.14.54" + resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.54.tgz#d9918e9e4cb972f8d6dae8e8655bf9ee131eda34" + integrity sha512-qTHGQB8D1etd0u1+sB6p0ikLKRVuCWhYQhAHRPkO+OF3I/iSlTKNNS0Lh2Oc0g0UFGguaFZZiPJdJey3AGpAlw== + +esbuild-linux-ppc64le@0.14.54: + version "0.14.54" + resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.54.tgz#3f9a0f6d41073fb1a640680845c7de52995f137e" + integrity sha512-j3OMlzHiqwZBDPRCDFKcx595XVfOfOnv68Ax3U4UKZ3MTYQB5Yz3X1mn5GnodEVYzhtZgxEBidLWeIs8FDSfrQ== + +esbuild-linux-riscv64@0.14.54: + version "0.14.54" + resolved "https://registry.yarnpkg.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.54.tgz#618853c028178a61837bc799d2013d4695e451c8" + integrity sha512-y7Vt7Wl9dkOGZjxQZnDAqqn+XOqFD7IMWiewY5SPlNlzMX39ocPQlOaoxvT4FllA5viyV26/QzHtvTjVNOxHZg== + +esbuild-linux-s390x@0.14.54: + version "0.14.54" + resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.54.tgz#d1885c4c5a76bbb5a0fe182e2c8c60eb9e29f2a6" + integrity sha512-zaHpW9dziAsi7lRcyV4r8dhfG1qBidQWUXweUjnw+lliChJqQr+6XD71K41oEIC3Mx1KStovEmlzm+MkGZHnHA== + +esbuild-netbsd-64@0.14.54: + version "0.14.54" + resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.54.tgz#69ae917a2ff241b7df1dbf22baf04bd330349e81" + integrity sha512-PR01lmIMnfJTgeU9VJTDY9ZerDWVFIUzAtJuDHwwceppW7cQWjBBqP48NdeRtoP04/AtO9a7w3viI+PIDr6d+w== + +esbuild-openbsd-64@0.14.54: + version "0.14.54" + resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.54.tgz#db4c8495287a350a6790de22edea247a57c5d47b" + integrity sha512-Qyk7ikT2o7Wu76UsvvDS5q0amJvmRzDyVlL0qf5VLsLchjCa1+IAvd8kTBgUxD7VBUUVgItLkk609ZHUc1oCaw== + +esbuild-sunos-64@0.14.54: + version "0.14.54" + resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.54.tgz#54287ee3da73d3844b721c21bc80c1dc7e1bf7da" + integrity sha512-28GZ24KmMSeKi5ueWzMcco6EBHStL3B6ubM7M51RmPwXQGLe0teBGJocmWhgwccA1GeFXqxzILIxXpHbl9Q/Kw== + +esbuild-windows-32@0.14.54: + version "0.14.54" + resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.14.54.tgz#f8aaf9a5667630b40f0fb3aa37bf01bbd340ce31" + integrity sha512-T+rdZW19ql9MjS7pixmZYVObd9G7kcaZo+sETqNH4RCkuuYSuv9AGHUVnPoP9hhuE1WM1ZimHz1CIBHBboLU7w== + +esbuild-windows-64@0.14.54: + version "0.14.54" + resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.14.54.tgz#bf54b51bd3e9b0f1886ffdb224a4176031ea0af4" + integrity sha512-AoHTRBUuYwXtZhjXZbA1pGfTo8cJo3vZIcWGLiUcTNgHpJJMC1rVA44ZereBHMJtotyN71S8Qw0npiCIkW96cQ== + +esbuild-windows-arm64@0.14.54: + version "0.14.54" + resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.54.tgz#937d15675a15e4b0e4fafdbaa3a01a776a2be982" + integrity sha512-M0kuUvXhot1zOISQGXwWn6YtS+Y/1RT9WrVIOywZnJHo3jCDyewAc79aKNQWFCQm+xNHVTq9h8dZKvygoXQQRg== + +esbuild@^0.14.2: + version "0.14.54" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.14.54.tgz#8b44dcf2b0f1a66fc22459943dccf477535e9aa2" + integrity sha512-Cy9llcy8DvET5uznocPyqL3BFRrFXSVqbgpMJ9Wz8oVjZlh/zUSNbPRbov0VX7VxN2JH1Oa0uNxZ7eLRb62pJA== + optionalDependencies: + "@esbuild/linux-loong64" "0.14.54" + esbuild-android-64 "0.14.54" + esbuild-android-arm64 "0.14.54" + esbuild-darwin-64 "0.14.54" + esbuild-darwin-arm64 "0.14.54" + esbuild-freebsd-64 "0.14.54" + esbuild-freebsd-arm64 "0.14.54" + esbuild-linux-32 "0.14.54" + esbuild-linux-64 "0.14.54" + esbuild-linux-arm "0.14.54" + esbuild-linux-arm64 "0.14.54" + esbuild-linux-mips64le "0.14.54" + esbuild-linux-ppc64le "0.14.54" + esbuild-linux-riscv64 "0.14.54" + esbuild-linux-s390x "0.14.54" + esbuild-netbsd-64 "0.14.54" + esbuild-openbsd-64 "0.14.54" + esbuild-sunos-64 "0.14.54" + esbuild-windows-32 "0.14.54" + esbuild-windows-64 "0.14.54" + esbuild-windows-arm64 "0.14.54"