index.3d64fa62.js.map 110.7 KB
Newer Older
6
622eda98dfef6c4fdb84ccca 已提交
1
{"version":3,"file":"index.3d64fa62.js","sources":["../../vite/modulepreload-polyfill","../../src/core/index.ts","../../src/player/index.ts","../../src/static/textures/block/stone.png","../../src/static/textures/block/coal_ore.png","../../src/static/textures/block/iron_ore.png","../../src/static/textures/block/grass_block_side.png","../../src/static/textures/block/grass_top_green.png","../../src/static/textures/block/dirt.png","../../src/static/textures/block/oak_log.png","../../src/static/textures/block/oak_log_top.png","../../src/static/textures/block/oak_leaves.png","../../src/static/textures/block/sand.png","../../src/static/textures/block/oak_planks.png","../../src/static/textures/block/diamond_block.png","../../src/static/textures/block/quartz_block_side.png","../../src/static/textures/block/glass.png","../../src/static/textures/block/bedrock.png","../../src/terrain/mesh/materials.ts","../../src/terrain/mesh/block.ts","../../src/terrain/highlight/index.ts","../../src/terrain/noise/index.ts","../../src/terrain/index.ts","../../src/utils/index.ts","../../src/control/index.ts","../../src/ui/fps/index.ts","../../src/static/block-icon/grass.png","../../src/static/block-icon/stone.png","../../src/static/block-icon/tree.png","../../src/static/block-icon/wood.png","../../src/static/block-icon/diamond.png","../../src/static/block-icon/quartz.png","../../src/static/block-icon/glass.png","../../src/ui/bag/index.ts","../../src/ui/joystick/joystick.html?raw","../../src/ui/joystick/index.ts","../../src/ui/index.ts","../../src/audio/musics/hal3.ogg","../../src/audio/blocks/grass1.ogg","../../src/audio/blocks/grass2.ogg","../../src/audio/blocks/grass3.ogg","../../src/audio/blocks/grass4.ogg","../../src/audio/blocks/sand1.ogg","../../src/audio/blocks/sand2.ogg","../../src/audio/blocks/sand3.ogg","../../src/audio/blocks/sand4.ogg","../../src/audio/blocks/stone1.ogg","../../src/audio/blocks/stone2.ogg","../../src/audio/blocks/stone3.ogg","../../src/audio/blocks/stone4.ogg","../../src/audio/blocks/dirt1.ogg","../../src/audio/blocks/dirt2.ogg","../../src/audio/blocks/dirt3.ogg","../../src/audio/blocks/dirt4.ogg","../../src/audio/blocks/tree1.ogg","../../src/audio/blocks/tree2.ogg","../../src/audio/blocks/tree3.ogg","../../src/audio/blocks/tree4.ogg","../../src/audio/blocks/leaf1.ogg","../../src/audio/blocks/leaf2.ogg","../../src/audio/blocks/leaf3.ogg","../../src/audio/blocks/leaf4.ogg","../../src/audio/index.ts","../../src/main.ts"],"sourcesContent":["const p = function polyfill() {\n    const relList = document.createElement('link').relList;\n    if (relList && relList.supports && relList.supports('modulepreload')) {\n        return;\n    }\n    for (const link of document.querySelectorAll('link[rel=\"modulepreload\"]')) {\n        processPreload(link);\n    }\n    new MutationObserver((mutations) => {\n        for (const mutation of mutations) {\n            if (mutation.type !== 'childList') {\n                continue;\n            }\n            for (const node of mutation.addedNodes) {\n                if (node.tagName === 'LINK' && node.rel === 'modulepreload')\n                    processPreload(node);\n            }\n        }\n    }).observe(document, { childList: true, subtree: true });\n    function getFetchOpts(script) {\n        const fetchOpts = {};\n        if (script.integrity)\n            fetchOpts.integrity = script.integrity;\n        if (script.referrerpolicy)\n            fetchOpts.referrerPolicy = script.referrerpolicy;\n        if (script.crossorigin === 'use-credentials')\n            fetchOpts.credentials = 'include';\n        else if (script.crossorigin === 'anonymous')\n            fetchOpts.credentials = 'omit';\n        else\n            fetchOpts.credentials = 'same-origin';\n        return fetchOpts;\n    }\n    function processPreload(link) {\n        if (link.ep)\n            // ep marker = processed\n            return;\n        link.ep = true;\n        // prepopulate the load record\n        const fetchOpts = getFetchOpts(link);\n        fetch(link.href, fetchOpts);\n    }\n};__VITE_IS_MODERN__&&p();","import * as THREE from 'three'\n\nexport default class Core {\n  constructor() {\n    this.camera = new THREE.PerspectiveCamera()\n    this.renderer = new THREE.WebGLRenderer()\n    this.scene = new THREE.Scene()\n    this.initScene()\n    this.initRenderer()\n    this.initCamera()\n  }\n\n  camera: THREE.PerspectiveCamera\n  scene: THREE.Scene\n  renderer: THREE.Renderer\n\n  initCamera = () => {\n    this.camera.fov = 50\n    this.camera.aspect = window.innerWidth / window.innerHeight\n    this.camera.near = 0.01\n    this.camera.far = 500\n    this.camera.updateProjectionMatrix()\n    this.camera.position.set(8, 50, 8)\n\n    this.camera.lookAt(100, 30, 100)\n\n    window.addEventListener('resize', () => {\n      this.camera.aspect = window.innerWidth / window.innerHeight\n      this.camera.updateProjectionMatrix()\n    })\n  }\n\n  initScene = () => {\n    this.scene = new THREE.Scene()\n    const backgroundColor = 0x87ceeb\n\n    this.scene.fog = new THREE.Fog(backgroundColor, 1, 96)\n    this.scene.background = new THREE.Color(backgroundColor)\n\n    const sunLight = new THREE.PointLight(0xffffff, 0.5)\n    sunLight.position.set(500, 500, 500)\n    this.scene.add(sunLight)\n\n    const sunLight2 = new THREE.PointLight(0xffffff, 0.2)\n    sunLight2.position.set(-500, 500, -500)\n    this.scene.add(sunLight2)\n\n    const reflectionLight = new THREE.AmbientLight(0x404040)\n    this.scene.add(reflectionLight)\n  }\n\n  initRenderer = () => {\n    this.renderer.setSize(window.innerWidth, window.innerHeight)\n    document.body.appendChild(this.renderer.domElement)\n\n    window.addEventListener('resize', () => {\n      this.renderer.setSize(window.innerWidth, window.innerHeight)\n    })\n  }\n}\n","export enum Mode {\n  walking = 'walking',\n  sprinting = 'sprinting',\n  flying = 'flying',\n  sprintFlying = 'sprintFlying',\n  sneaking = 'sneaking'\n}\n\nexport enum Speed {\n  // walking = 4.317,\n  walking = 5.612,\n  sprinting = 5.612,\n  // flying = 10.89,\n  flying = 21.78,\n  sprintFlying = 21.78,\n  sneaking = 1.95\n}\nexport default class Player {\n  mode = Mode.walking\n  speed = Speed[this.mode]\n\n  setMode(Mode: Mode) {\n    this.mode = Mode\n    this.speed = Speed[this.mode]\n  }\n  falling = 38.4\n\n  jump = 1.2522\n\n  body = {\n    height: 1.8,\n    width: 0.5\n  }\n}\n","export default \"__VITE_ASSET__fa5e82cb__\"","export default \"__VITE_ASSET__29c9a29e__\"","export default \"__VITE_ASSET__78230e9e__\"","export default \"__VITE_ASSET__1f5d4845__\"","export default \"__VITE_ASSET__be9cf310__\"","export default \"__VITE_ASSET__fb045025__\"","export default \"__VITE_ASSET__fc1a2462__\"","export default \"__VITE_ASSET__6a68c340__\"","export default \"__VITE_ASSET__776aee85__\"","export default \"__VITE_ASSET__f4bf1751__\"","export default \"__VITE_ASSET__be4a7f91__\"","export default \"__VITE_ASSET__fb45cc99__\"","export default \"__VITE_ASSET__0e4d401c__\"","export default \"__VITE_ASSET__17e849a2__\"","export default \"__VITE_ASSET__3e3a8330__\"","import * as THREE from 'three'\nimport stone from '../../static/textures/block/stone.png'\nimport coal_ore from '../../static/textures/block/coal_ore.png'\nimport iron_ore from '../../static/textures/block/iron_ore.png'\nimport grass_side from '../../static/textures/block/grass_block_side.png'\nimport grass_top_green from '../../static/textures/block/grass_top_green.png'\nimport dirt from '../../static/textures/block/dirt.png'\nimport oak_log from '../../static/textures/block/oak_log.png'\nimport oak_log_top from '../../static/textures/block/oak_log_top.png'\nimport oak_leaves from '../../static/textures/block/oak_leaves.png'\nimport sand from '../../static/textures/block/sand.png'\n// import water from '../../static/textures/block/water.png'\nimport oak_wood from '../../static/textures/block/oak_planks.png'\nimport diamond from '../../static/textures/block/diamond_block.png'\nimport quartz from '../../static/textures/block/quartz_block_side.png'\nimport glass from '../../static/textures/block/glass.png'\nimport bedrock from '../../static/textures/block/bedrock.png'\n\nexport enum MaterialType {\n  grass = 'grass',\n  dirt = 'dirt',\n  tree = 'tree',\n  leaf = 'leaf',\n  sand = 'sand',\n  // water = 'water',\n  stone = 'stone',\n  coal = 'coal',\n  wood = 'wood',\n  diamond = 'diamond',\n  quartz = 'quartz',\n  glass = 'glass',\n  bedrock = 'bedrock'\n}\nlet loader = new THREE.TextureLoader()\n\n// load texture\nconst grassTopMaterial = loader.load(grass_top_green)\nconst grassMaterial = loader.load(grass_side)\nconst treeMaterial = loader.load(oak_log)\nconst treeTopMaterial = loader.load(oak_log_top)\nconst dirtMaterial = loader.load(dirt)\nconst stoneMaterial = loader.load(stone)\nconst coalMaterial = loader.load(coal_ore)\nconst ironMaterial = loader.load(iron_ore)\nconst leafMaterial = loader.load(oak_leaves)\nconst sandMaterial = loader.load(sand)\n// const waterMaterial = loader.load(water)\nconst woodMaterial = loader.load(oak_wood)\nconst diamondMaterial = loader.load(diamond)\nconst quartzMaterial = loader.load(quartz)\nconst glassMaterial = loader.load(glass)\nconst bedrockMaterial = loader.load(bedrock)\n\n// pixelate texture\ngrassTopMaterial.magFilter = THREE.NearestFilter\ngrassMaterial.magFilter = THREE.NearestFilter\ntreeMaterial.magFilter = THREE.NearestFilter\ntreeTopMaterial.magFilter = THREE.NearestFilter\ndirtMaterial.magFilter = THREE.NearestFilter\nstoneMaterial.magFilter = THREE.NearestFilter\ncoalMaterial.magFilter = THREE.NearestFilter\nironMaterial.magFilter = THREE.NearestFilter\nleafMaterial.magFilter = THREE.NearestFilter\nsandMaterial.magFilter = THREE.NearestFilter\n// waterMaterial.magFilter = THREE.NearestFilter\nwoodMaterial.magFilter = THREE.NearestFilter\ndiamondMaterial.magFilter = THREE.NearestFilter\nquartzMaterial.magFilter = THREE.NearestFilter\nglassMaterial.magFilter = THREE.NearestFilter\nbedrockMaterial.magFilter = THREE.NearestFilter\n\nexport default class Materials {\n  materials = {\n    grass: [\n      new THREE.MeshStandardMaterial({ map: grassMaterial }),\n      new THREE.MeshStandardMaterial({ map: grassMaterial }),\n      new THREE.MeshStandardMaterial({\n        map: grassTopMaterial\n      }),\n      new THREE.MeshStandardMaterial({ map: dirtMaterial }),\n      new THREE.MeshStandardMaterial({ map: grassMaterial }),\n      new THREE.MeshStandardMaterial({ map: grassMaterial })\n    ],\n    dirt: new THREE.MeshStandardMaterial({ map: dirtMaterial }),\n    sand: new THREE.MeshStandardMaterial({ map: sandMaterial }),\n    tree: [\n      new THREE.MeshStandardMaterial({ map: treeMaterial }),\n      new THREE.MeshStandardMaterial({ map: treeMaterial }),\n      new THREE.MeshStandardMaterial({ map: treeTopMaterial }),\n      new THREE.MeshStandardMaterial({ map: treeTopMaterial }),\n      new THREE.MeshStandardMaterial({ map: treeMaterial }),\n      new THREE.MeshStandardMaterial({ map: treeMaterial })\n    ],\n    leaf: new THREE.MeshStandardMaterial({\n      map: leafMaterial,\n      color: new THREE.Color(0, 1, 0),\n      transparent: true\n    }),\n    // water: new THREE.MeshStandardMaterial({\n    //   map: waterMaterial,\n    //   transparent: true,\n    //   opacity: 0.7\n    // }),\n    stone: new THREE.MeshStandardMaterial({ map: stoneMaterial }),\n    coal: new THREE.MeshStandardMaterial({ map: coalMaterial }),\n    wood: new THREE.MeshStandardMaterial({ map: woodMaterial }),\n    diamond: new THREE.MeshStandardMaterial({ map: diamondMaterial }),\n    quartz: new THREE.MeshStandardMaterial({ map: quartzMaterial }),\n    glass: new THREE.MeshStandardMaterial({\n      map: glassMaterial,\n      transparent: true\n    }),\n    bedrock: new THREE.MeshStandardMaterial({ map: bedrockMaterial })\n  }\n\n  get = (\n    type: MaterialType\n  ): THREE.MeshStandardMaterial | THREE.MeshStandardMaterial[] => {\n    return this.materials[type]\n  }\n}\n","import { BlockType } from '../index'\n\n/**\n * Custom block\n */\nexport default class Block {\n  object: any\n  constructor(\n    x: number,\n    y: number,\n    z: number,\n    type: BlockType,\n    placed: boolean\n  ) {\n    this.x = x\n    this.y = y\n    this.z = z\n    this.type = type\n    this.placed = placed\n  }\n  x: number\n  y: number\n  z: number\n  type: BlockType\n  placed: boolean\n}\n","import * as THREE from 'three'\nimport Terrain from '..'\n\n/**\n * Highlight block on crosshair\n */\nexport default class BlockHighlight {\n  constructor(\n    scene: THREE.Scene,\n    camera: THREE.PerspectiveCamera,\n    terrain: Terrain\n  ) {\n    this.camera = camera\n    this.scene = scene\n    this.terrain = terrain\n    this.raycaster = new THREE.Raycaster()\n    this.raycaster.far = 8\n  }\n\n  scene: THREE.Scene\n  camera: THREE.PerspectiveCamera\n  terrain: Terrain\n  raycaster: THREE.Raycaster\n  block: THREE.Intersection | null = null\n\n  // highlight block mesh\n  geometry = new THREE.BoxGeometry(1.01, 1.01, 1.01)\n  material = new THREE.MeshStandardMaterial({\n    transparent: true,\n    opacity: 0.25\n    // depthWrite: false\n  })\n  mesh = new THREE.Mesh(new THREE.BoxGeometry(), this.material)\n\n  // block simulation\n  index = 0\n  instanceMesh = new THREE.InstancedMesh(\n    new THREE.BoxGeometry(),\n    new THREE.MeshBasicMaterial(),\n    1000\n  )\n\n  update() {\n    // remove last highlight and reset block simulation\n    this.scene.remove(this.mesh)\n    this.index = 0\n    this.instanceMesh.instanceMatrix = new THREE.InstancedBufferAttribute(\n      new Float32Array(1000 * 16),\n      16\n    )\n\n    const position = this.camera.position\n    const matrix = new THREE.Matrix4()\n    const idMap = new Map<string, number>()\n    const noise = this.terrain.noise\n\n    let xPos = Math.round(position.x)\n    let zPos = Math.round(position.z)\n\n    for (let i = -8; i < 8; i++) {\n      for (let j = -8; j < 8; j++) {\n        // check terrain\n        let x = xPos + i\n        let z = zPos + j\n        let y =\n          Math.floor(\n            noise.get(x / noise.gap, z / noise.gap, noise.seed) * noise.amp\n          ) + 30\n\n        idMap.set(`${x}_${y}_${z}`, this.index)\n        matrix.setPosition(x, y, z)\n        this.instanceMesh.setMatrixAt(this.index++, matrix)\n\n        let stoneOffset =\n          noise.get(x / noise.stoneGap, z / noise.stoneGap, noise.stoneSeed) *\n          noise.stoneAmp\n\n        let treeOffset =\n          noise.get(x / noise.treeGap, z / noise.treeGap, noise.treeSeed) *\n          noise.treeAmp\n\n        // check tree\n        if (\n          treeOffset > noise.treeThreshold &&\n          y - 30 >= -3 &&\n          stoneOffset < noise.stoneThreshold\n        ) {\n          for (let t = 1; t <= noise.treeHeight; t++) {\n            idMap.set(`${x}_${y + t}_${z}`, this.index)\n            matrix.setPosition(x, y + t, z)\n            this.instanceMesh.setMatrixAt(this.index++, matrix)\n          }\n\n          // leaf\n          // for (let i = -3; i < 3; i++) {\n          //   for (let j = -3; j < 3; j++) {\n          //     for (let k = -3; k < 3; k++) {\n          //       if (i === 0 && k === 0) {\n          //         continue\n          //       }\n          //     let leafOffset =\n          //       noise.get(\n          //         (x + i + j) / noise.leafGap,\n          //         (z + k) / noise.leafGap,\n          //         noise.leafSeed\n          //       ) * noise.leafAmp\n\n          //       if (leafOffset > noise.leafThreshold) {\n          //         idMap.set(\n          //           `${x + i}_${y + noise.treeHeight + j}_${z + k}`,\n          //           this.index\n          //         )\n          //         matrix.setPosition(x + i, y + noise.treeHeight + j, z + k)\n          //         this.instanceMesh.setMatrixAt(this.index++, matrix)\n          //       }\n          //     }\n          //   }\n          // }\n        }\n      }\n    }\n\n    // check custom blocks\n    for (const block of this.terrain.customBlocks) {\n      if (block.placed) {\n        matrix.setPosition(block.x, block.y, block.z)\n        this.instanceMesh.setMatrixAt(this.index++, matrix)\n      } else {\n        if (idMap.has(`${block.x}_${block.y}_${block.z}`)) {\n          let id = idMap.get(`${block.x}_${block.y}_${block.z}`)\n          this.instanceMesh.setMatrixAt(\n            id!,\n            new THREE.Matrix4().set(\n              0,\n              0,\n              0,\n              0,\n              0,\n              0,\n              0,\n              0,\n              0,\n              0,\n              0,\n              0,\n              0,\n              0,\n              0,\n              0\n            )\n          )\n        }\n      }\n    }\n\n    // highlight new block\n    this.raycaster.setFromCamera({ x: 0, y: 0 }, this.camera)\n    this.block = this.raycaster.intersectObject(this.instanceMesh)[0]\n    if (\n      this.block &&\n      this.block.object instanceof THREE.InstancedMesh &&\n      typeof this.block.instanceId === 'number'\n    ) {\n      this.mesh = new THREE.Mesh(this.geometry, this.material)\n      let matrix = new THREE.Matrix4()\n      this.block.object.getMatrixAt(this.block.instanceId, matrix)\n      const position = new THREE.Vector3().setFromMatrixPosition(matrix)\n\n      this.mesh.position.set(position.x, position.y, position.z)\n      this.scene.add(this.mesh)\n    }\n  }\n}\n","import { ImprovedNoise } from 'three/examples/jsm/math/ImprovedNoise'\n// import { SimplexNoise } from 'three/examples/jsm/math/SimplexNoise'\n\nexport default class Noise {\n  noise = new ImprovedNoise()\n  seed = Math.random()\n  gap = 22\n  amp = 8\n\n  stoneSeed = this.seed * 0.4\n  stoneGap = 12\n  stoneAmp = 8\n  stoneThreshold = 3.5\n\n  coalSeed = this.seed * 0.5\n  coalGap = 3\n  coalAmp = 8\n  coalThreshold = 3\n\n  treeSeed = this.seed * 0.7\n  treeGap = 2\n  treeAmp = 6\n  treeHeight = 10\n  treeThreshold = 4\n\n  leafSeed = this.seed * 0.8\n  leafGap = 2\n  leafAmp = 5\n  leafThreshold = -0.03\n\n  get = (x: number, y: number, z: number) => {\n    return this.noise.noise(x, y, z)\n  }\n}\n","import * as THREE from 'three'\nimport Materials, { MaterialType } from './mesh/materials'\nimport Block from './mesh/block'\nimport Highlight from './highlight'\nimport Noise from './noise'\n\nimport Generate from './worker/generate?worker'\n\nexport enum BlockType {\n  grass = 0,\n  sand = 1,\n  tree = 2,\n  leaf = 3,\n  dirt = 4,\n  stone = 5,\n  coal = 6,\n  wood = 7,\n  diamond = 8,\n  quartz = 9,\n  glass = 10,\n  bedrock = 11\n}\nexport default class Terrain {\n  constructor(scene: THREE.Scene, camera: THREE.PerspectiveCamera) {\n    this.scene = scene\n    this.camera = camera\n    this.maxCount =\n      (this.distance * this.chunkSize * 2 + this.chunkSize) ** 2 + 500\n    this.highlight = new Highlight(scene, camera, this)\n    this.scene.add(this.cloud)\n\n    // generate worker callback handler\n    this.generateWorker.onmessage = (\n      msg: MessageEvent<{\n        idMap: Map<string, number>\n        arrays: ArrayLike<number>[]\n        blocksCount: number[]\n      }>\n    ) => {\n      this.resetBlocks()\n      this.idMap = msg.data.idMap\n      this.blocksCount = msg.data.blocksCount\n\n      for (let i = 0; i < msg.data.arrays.length; i++) {\n        this.blocks[i].instanceMatrix = new THREE.InstancedBufferAttribute(\n          (this.blocks[i].instanceMatrix.array = msg.data.arrays[i]),\n          16\n        )\n      }\n\n      for (const block of this.blocks) {\n        block.instanceMatrix.needsUpdate = true\n      }\n    }\n  }\n  // core properties\n  scene: THREE.Scene\n  camera: THREE.PerspectiveCamera\n  distance = 3\n  chunkSize = 24\n\n  // terrain properties\n  maxCount: number\n  chunk = new THREE.Vector2(0, 0)\n  previousChunk = new THREE.Vector2(0, 0)\n  noise = new Noise()\n\n  // materials\n  materials = new Materials()\n  materialType = [\n    MaterialType.grass,\n    MaterialType.sand,\n    MaterialType.tree,\n    MaterialType.leaf,\n    MaterialType.dirt,\n    MaterialType.stone,\n    MaterialType.coal,\n    MaterialType.wood,\n    MaterialType.diamond,\n    MaterialType.quartz,\n    MaterialType.glass,\n    MaterialType.bedrock\n  ]\n\n  // other properties\n  blocks: THREE.InstancedMesh[] = []\n  blocksCount: number[] = []\n  blocksFactor = [1, 0.2, 0.1, 0.7, 0.1, 0.2, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]\n\n  customBlocks: Block[] = []\n  highlight: Highlight\n\n  idMap = new Map<string, number>()\n  generateWorker = new Generate()\n\n  // cloud\n  cloud = new THREE.InstancedMesh(\n    new THREE.BoxGeometry(20, 5, 14),\n    new THREE.MeshStandardMaterial({\n      transparent: true,\n      color: 0xffffff,\n      opacity: 0.4\n    }),\n    1000\n  )\n  cloudCount = 0\n  cloudGap = 5\n\n  getCount = (type: BlockType) => {\n    return this.blocksCount[type]\n  }\n\n  setCount = (type: BlockType) => {\n    this.blocksCount[type] = this.blocksCount[type] + 1\n  }\n\n  initBlocks = () => {\n    // reset\n    for (const block of this.blocks) {\n      this.scene.remove(block)\n    }\n    this.blocks = []\n\n    // create instance meshes\n    const geometry = new THREE.BoxGeometry()\n\n    for (let i = 0; i < this.materialType.length; i++) {\n      let block = new THREE.InstancedMesh(\n        geometry,\n        this.materials.get(this.materialType[i]),\n        this.maxCount * this.blocksFactor[i]\n      )\n      block.name = BlockType[i]\n      this.blocks.push(block)\n      this.scene.add(block)\n    }\n\n    this.blocksCount = new Array(this.materialType.length).fill(0)\n  }\n\n  resetBlocks = () => {\n    // reest count and instance matrix\n    for (let i = 0; i < this.blocks.length; i++) {\n      this.blocks[i].instanceMatrix = new THREE.InstancedBufferAttribute(\n        new Float32Array(this.maxCount * this.blocksFactor[i] * 16),\n        16\n      )\n    }\n  }\n\n  generate = () => {\n    this.blocksCount = new Array(this.blocks.length).fill(0)\n    // post work to generate worker\n    this.generateWorker.postMessage({\n      distance: this.distance,\n      chunk: this.chunk,\n      noiseSeed: this.noise.seed,\n      treeSeed: this.noise.treeSeed,\n      stoneSeed: this.noise.stoneSeed,\n      coalSeed: this.noise.coalSeed,\n      idMap: new Map<string, number>(),\n      blocksFactor: this.blocksFactor,\n      blocksCount: this.blocksCount,\n      customBlocks: this.customBlocks,\n      chunkSize: this.chunkSize\n    })\n\n    // cloud\n\n    if (this.cloudGap++ > 5) {\n      this.cloudGap = 0\n      this.cloud.instanceMatrix = new THREE.InstancedBufferAttribute(\n        new Float32Array(1000 * 16),\n        16\n      )\n      this.cloudCount = 0\n      for (\n        let x =\n          -this.chunkSize * this.distance * 3 + this.chunkSize * this.chunk.x;\n        x <\n        this.chunkSize * this.distance * 3 +\n          this.chunkSize +\n          this.chunkSize * this.chunk.x;\n        x += 20\n      ) {\n        for (\n          let z =\n            -this.chunkSize * this.distance * 3 + this.chunkSize * this.chunk.y;\n          z <\n          this.chunkSize * this.distance * 3 +\n            this.chunkSize +\n            this.chunkSize * this.chunk.y;\n          z += 20\n        ) {\n          const matrix = new THREE.Matrix4()\n          matrix.setPosition(x, 80 + (Math.random() - 0.5) * 30, z)\n\n          if (Math.random() > 0.8) {\n            this.cloud.setMatrixAt(this.cloudCount++, matrix)\n          }\n        }\n      }\n      this.cloud.instanceMatrix.needsUpdate = true\n    }\n  }\n\n  // generate adjacent blocks after removing a block (vertical infinity world)\n  generateAdjacentBlocks = (position: THREE.Vector3) => {\n    const { x, y, z } = position\n    const noise = this.noise\n    const yOffset = Math.floor(\n      noise.get(x / noise.gap, z / noise.gap, noise.seed) * noise.amp\n    )\n\n    if (y > 30 + yOffset) {\n      return\n    }\n\n    const stoneOffset =\n      noise.get(x / noise.stoneGap, z / noise.stoneGap, noise.stoneSeed) *\n      noise.stoneAmp\n\n    let type: BlockType\n\n    if (stoneOffset > noise.stoneThreshold || y < 23) {\n      type = BlockType.stone\n    } else {\n      if (yOffset < -3) {\n        type = BlockType.sand\n      } else {\n        type = BlockType.dirt\n      }\n    }\n\n    this.buildBlock(new THREE.Vector3(x, y - 1, z), type)\n    this.buildBlock(new THREE.Vector3(x, y + 1, z), type)\n    this.buildBlock(new THREE.Vector3(x - 1, y, z), type)\n    this.buildBlock(new THREE.Vector3(x + 1, y, z), type)\n    this.buildBlock(new THREE.Vector3(x, y, z - 1), type)\n    this.buildBlock(new THREE.Vector3(x, y, z + 1), type)\n\n    this.blocks[type].instanceMatrix.needsUpdate = true\n  }\n\n  buildBlock = (position: THREE.Vector3, type: BlockType) => {\n    const noise = this.noise\n    // check if it's natural terrain\n    const yOffset = Math.floor(\n      noise.get(position.x / noise.gap, position.z / noise.gap, noise.seed) *\n        noise.amp\n    )\n    if (position.y >= 30 + yOffset || position.y < 0) {\n      return\n    }\n\n    position.y === 0 && (type = BlockType.bedrock)\n\n    // check custom blocks\n    for (const block of this.customBlocks) {\n      if (\n        block.x === position.x &&\n        block.y === position.y &&\n        block.z === position.z\n      ) {\n        return\n      }\n    }\n\n    // build block\n    this.customBlocks.push(\n      new Block(position.x, position.y, position.z, type, true)\n    )\n\n    const matrix = new THREE.Matrix4()\n    matrix.setPosition(position)\n    this.blocks[type].setMatrixAt(this.getCount(type), matrix)\n    this.blocks[type].instanceMatrix.needsUpdate = true\n    this.setCount(type)\n  }\n\n  update = () => {\n    this.chunk.set(\n      Math.floor(this.camera.position.x / this.chunkSize),\n      Math.floor(this.camera.position.z / this.chunkSize)\n    )\n\n    //generate terrain when getting into new chunk\n    if (\n      this.chunk.x !== this.previousChunk.x ||\n      this.chunk.y !== this.previousChunk.y\n    ) {\n      this.generate()\n    }\n\n    this.previousChunk.copy(this.chunk)\n\n    this.highlight.update()\n  }\n}\n","export const htmlToDom = (html: string) => {\n  const templateDom = document.createElement('template')\n  templateDom.innerHTML = html\n  window.document.body.appendChild(templateDom.content)\n}\n\nexport const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(\n  navigator.userAgent\n)\n","import * as THREE from 'three'\nimport { PointerLockControls } from 'three/examples/jsm/controls/PointerLockControls'\nimport Player, { Mode } from '../player'\nimport Terrain, { BlockType } from '../terrain'\n\nimport Block from '../terrain/mesh/block'\nimport Noise from '../terrain/noise'\nimport Audio from '../audio'\nimport { isMobile } from '../utils'\nenum Side {\n  front,\n  back,\n  left,\n  right,\n  down,\n  up\n}\n\nexport default class Control {\n  constructor(\n    scene: THREE.Scene,\n    camera: THREE.PerspectiveCamera,\n    player: Player,\n    terrain: Terrain,\n    audio: Audio\n  ) {\n    this.scene = scene\n    this.camera = camera\n    this.player = player\n    this.terrain = terrain\n    this.control = new PointerLockControls(camera, document.body)\n    this.audio = audio\n\n    this.raycaster = new THREE.Raycaster()\n    this.raycaster.far = 8\n    this.far = this.player.body.height\n\n    this.initRayCaster()\n    this.initEventListeners()\n  }\n\n  // core properties\n  scene: THREE.Scene\n  camera: THREE.PerspectiveCamera\n  player: Player\n  terrain: Terrain\n  control: PointerLockControls\n  audio: Audio\n  velocity = new THREE.Vector3(0, 0, 0)\n\n  // collide and jump properties\n  frontCollide = false\n  backCollide = false\n  leftCollide = false\n  rightCollide = false\n  downCollide = true\n  upCollide = false\n  isJumping = false\n\n  raycasterDown = new THREE.Raycaster()\n  raycasterUp = new THREE.Raycaster()\n  raycasterFront = new THREE.Raycaster()\n  raycasterBack = new THREE.Raycaster()\n  raycasterRight = new THREE.Raycaster()\n  raycasterLeft = new THREE.Raycaster()\n\n  tempMesh = new THREE.InstancedMesh(\n    new THREE.BoxGeometry(1, 1, 1),\n    new THREE.MeshBasicMaterial(),\n    100\n  )\n  tempMeshMatrix = new THREE.InstancedBufferAttribute(\n    new Float32Array(100 * 16),\n    16\n  )\n\n  // other properties\n  p1 = performance.now()\n  p2 = performance.now()\n  raycaster: THREE.Raycaster\n  far: number\n\n  holdingBlock = BlockType.grass\n  holdingBlocks = [\n    BlockType.grass,\n    BlockType.stone,\n    BlockType.tree,\n    BlockType.wood,\n    BlockType.diamond,\n    BlockType.quartz,\n    BlockType.glass,\n    BlockType.grass,\n    BlockType.grass,\n    BlockType.grass\n  ]\n  holdingIndex = 0\n  wheelGap = false\n  clickInterval?: ReturnType<typeof setInterval>\n  jumpInterval?: ReturnType<typeof setInterval>\n  mouseHolding = false\n  spaceHolding = false\n\n  initRayCaster = () => {\n    this.raycasterUp.ray.direction = new THREE.Vector3(0, 1, 0)\n    this.raycasterDown.ray.direction = new THREE.Vector3(0, -1, 0)\n    this.raycasterFront.ray.direction = new THREE.Vector3(1, 0, 0)\n    this.raycasterBack.ray.direction = new THREE.Vector3(-1, 0, 0)\n    this.raycasterLeft.ray.direction = new THREE.Vector3(0, 0, -1)\n    this.raycasterRight.ray.direction = new THREE.Vector3(0, 0, 1)\n\n    this.raycasterUp.far = 1.2\n    this.raycasterDown.far = this.player.body.height\n    this.raycasterFront.far = this.player.body.width\n    this.raycasterBack.far = this.player.body.width\n    this.raycasterLeft.far = this.player.body.width\n    this.raycasterRight.far = this.player.body.width\n  }\n\n  setMovementHandler = (e: KeyboardEvent) => {\n    if (e.repeat) {\n      return\n    }\n\n    switch (e.key) {\n      case 'q':\n        if (this.player.mode === Mode.walking) {\n          this.player.setMode(Mode.flying)\n        } else {\n          this.player.setMode(Mode.walking)\n        }\n        this.velocity.y = 0\n        this.velocity.x = 0\n        this.velocity.z = 0\n        break\n      case 'w':\n      case 'W':\n        this.velocity.x += this.player.speed\n        break\n      case 's':\n      case 'S':\n        this.velocity.x -= this.player.speed\n        break\n      case 'a':\n      case 'A':\n        this.velocity.z -= this.player.speed\n        break\n      case 'd':\n      case 'D':\n        this.velocity.z += this.player.speed\n        break\n      case ' ':\n        if (this.player.mode === Mode.walking) {\n          // jump\n          if (!this.isJumping) {\n            this.velocity.y = 8\n            this.isJumping = true\n            this.downCollide = false\n            this.far = 0\n            setTimeout(() => {\n              this.far = this.player.body.height\n            }, 300)\n          }\n        } else {\n          this.velocity.y += this.player.speed\n        }\n        if (this.player.mode === Mode.walking && !this.spaceHolding) {\n          this.spaceHolding = true\n          this.jumpInterval = setInterval(() => {\n            this.setMovementHandler(e)\n          }, 10)\n        }\n        break\n      case 'Shift':\n        if (this.player.mode === Mode.walking) {\n        } else {\n          this.velocity.y -= this.player.speed\n        }\n        break\n      default:\n        break\n    }\n  }\n\n  resetMovementHandler = (e: KeyboardEvent) => {\n    if (e.repeat) {\n      return\n    }\n\n    switch (e.key) {\n      case 'w':\n      case 'W':\n        this.velocity.x = 0\n        break\n      case 's':\n      case 'S':\n        this.velocity.x = 0\n        break\n      case 'a':\n      case 'A':\n        this.velocity.z = 0\n        break\n      case 'd':\n      case 'D':\n        this.velocity.z = 0\n        break\n      case ' ':\n        this.jumpInterval && clearInterval(this.jumpInterval)\n        this.spaceHolding = false\n        if (this.player.mode === Mode.walking) {\n          return\n        }\n        this.velocity.y = 0\n        break\n      case 'Shift':\n        if (this.player.mode === Mode.walking) {\n          return\n        }\n        this.velocity.y = 0\n        break\n      default:\n        break\n    }\n  }\n\n  mousedownHandler = (e: MouseEvent) => {\n    e.preventDefault()\n    // let p1 = performance.now()\n    this.raycaster.setFromCamera({ x: 0, y: 0 }, this.camera)\n    const block = this.raycaster.intersectObjects(this.terrain.blocks)[0]\n    const matrix = new THREE.Matrix4()\n\n    switch (e.button) {\n      // left click to remove block\n      case 0:\n        {\n          if (block && block.object instanceof THREE.InstancedMesh) {\n            // calculate position\n            block.object.getMatrixAt(block.instanceId!, matrix)\n            const position = new THREE.Vector3().setFromMatrixPosition(matrix)\n\n            // don't remove bedrock\n            if (\n              (BlockType[block.object.name as any] as unknown as BlockType) ===\n              BlockType.bedrock\n            ) {\n              this.terrain.generateAdjacentBlocks(position)\n              return\n            }\n\n            // remove the block\n            block.object.setMatrixAt(\n              block.instanceId!,\n              new THREE.Matrix4().set(\n                0,\n                0,\n                0,\n                0,\n                0,\n                0,\n                0,\n                0,\n                0,\n                0,\n                0,\n                0,\n                0,\n                0,\n                0,\n                0\n              )\n            )\n\n            // block and sound effect\n            this.audio.playSound(\n              BlockType[block.object.name as any] as unknown as BlockType\n            )\n\n            const mesh = new THREE.Mesh(\n              new THREE.BoxGeometry(1, 1, 1),\n              this.terrain.materials.get(\n                this.terrain.materialType[\n                parseInt(BlockType[block.object.name as any])\n                ]\n              )\n            )\n            mesh.position.set(position.x, position.y, position.z)\n            this.scene.add(mesh)\n            const time = performance.now()\n            let raf = 0\n            const animate = () => {\n              if (performance.now() - time > 250) {\n                this.scene.remove(mesh)\n                cancelAnimationFrame(raf)\n                return\n              }\n              raf = requestAnimationFrame(animate)\n              mesh.geometry.scale(0.85, 0.85, 0.85)\n            }\n            animate()\n\n            // update\n            block.object.instanceMatrix.needsUpdate = true\n\n            // check existence\n            let existed = false\n            for (const customBlock of this.terrain.customBlocks) {\n              if (\n                customBlock.x === position.x &&\n                customBlock.y === position.y &&\n                customBlock.z === position.z\n              ) {\n                existed = true\n                customBlock.placed = false\n              }\n            }\n\n            // add to custom blocks when it's not existed\n            if (!existed) {\n              this.terrain.customBlocks.push(\n                new Block(\n                  position.x,\n                  position.y,\n                  position.z,\n                  BlockType[block.object.name as any] as unknown as BlockType,\n                  false\n                )\n              )\n            }\n\n            // generate adjacent blocks\n            this.terrain.generateAdjacentBlocks(position)\n          }\n        }\n        break\n\n      // right click to put block\n      case 2:\n        {\n          if (block && block.object instanceof THREE.InstancedMesh) {\n            // calculate normal and position\n            const normal = block.face!.normal\n            block.object.getMatrixAt(block.instanceId!, matrix)\n            const position = new THREE.Vector3().setFromMatrixPosition(matrix)\n\n            // return when block overlaps with player\n            if (\n              position.x + normal.x === Math.round(this.camera.position.x) &&\n              position.z + normal.z === Math.round(this.camera.position.z) &&\n              (position.y + normal.y === Math.round(this.camera.position.y) ||\n                position.y + normal.y ===\n                Math.round(this.camera.position.y - 1))\n            ) {\n              return\n            }\n\n            // put the block\n            matrix.setPosition(\n              normal.x + position.x,\n              normal.y + position.y,\n              normal.z + position.z\n            )\n            this.terrain.blocks[this.holdingBlock].setMatrixAt(\n              this.terrain.getCount(this.holdingBlock),\n              matrix\n            )\n            this.terrain.setCount(this.holdingBlock)\n\n            //sound effect\n            this.audio.playSound(this.holdingBlock)\n\n            // update\n            this.terrain.blocks[this.holdingBlock].instanceMatrix.needsUpdate =\n              true\n\n            // add to custom blocks\n            this.terrain.customBlocks.push(\n              new Block(\n                normal.x + position.x,\n                normal.y + position.y,\n                normal.z + position.z,\n                this.holdingBlock,\n                true\n              )\n            )\n          }\n        }\n        break\n      default:\n        break\n    }\n\n    if (!isMobile && !this.mouseHolding) {\n      this.mouseHolding = true\n      this.clickInterval = setInterval(() => {\n        this.mousedownHandler(e)\n      }, 333)\n    }\n\n    // console.log(performance.now() - p1)\n  }\n  mouseupHandler = () => {\n    this.clickInterval && clearInterval(this.clickInterval)\n    this.mouseHolding = false\n  }\n\n  changeHoldingBlockHandler = (e: KeyboardEvent) => {\n    if (isNaN(parseInt(e.key)) || e.key === '0') {\n      return\n    }\n    this.holdingIndex = parseInt(e.key) - 1\n\n    this.holdingBlock = this.holdingBlocks[this.holdingIndex] ?? BlockType.grass\n  }\n\n  wheelHandler = (e: WheelEvent) => {\n    if (!this.wheelGap) {\n      this.wheelGap = true\n      setTimeout(() => {\n        this.wheelGap = false\n      }, 100)\n      if (e.deltaY > 0) {\n        this.holdingIndex++\n        this.holdingIndex > 9 && (this.holdingIndex = 0)\n      } else if (e.deltaY < 0) {\n        this.holdingIndex--\n        this.holdingIndex < 0 && (this.holdingIndex = 9)\n      }\n      this.holdingBlock =\n        this.holdingBlocks[this.holdingIndex] ?? BlockType.grass\n    }\n  }\n\n  initEventListeners = () => {\n    // add / remove handler when pointer lock / unlock\n    document.addEventListener('pointerlockchange', () => {\n      if (document.pointerLockElement) {\n        document.body.addEventListener(\n          'keydown',\n          this.changeHoldingBlockHandler\n        )\n        document.body.addEventListener('wheel', this.wheelHandler)\n        document.body.addEventListener('keydown', this.setMovementHandler)\n        document.body.addEventListener('keyup', this.resetMovementHandler)\n        document.body.addEventListener('mousedown', this.mousedownHandler)\n        document.body.addEventListener('mouseup', this.mouseupHandler)\n      } else {\n        document.body.removeEventListener(\n          'keydown',\n          this.changeHoldingBlockHandler\n        )\n        document.body.removeEventListener('wheel', this.wheelHandler)\n        document.body.removeEventListener('keydown', this.setMovementHandler)\n        document.body.removeEventListener('keyup', this.resetMovementHandler)\n        document.body.removeEventListener('mousedown', this.mousedownHandler)\n        document.body.removeEventListener('mouseup', this.mouseupHandler)\n        this.velocity = new THREE.Vector3(0, 0, 0)\n      }\n    })\n  }\n\n  // move along X with direction factor\n  moveX(distance: number, delta: number) {\n    this.camera.position.x +=\n      distance * (this.player.speed / Math.PI) * 2 * delta\n  }\n\n  // move along Z with direction factor\n  moveZ = (distance: number, delta: number) => {\n    this.camera.position.z +=\n      distance * (this.player.speed / Math.PI) * 2 * delta\n  }\n\n  // collide checking\n  collideCheckAll = (\n    position: THREE.Vector3,\n    noise: Noise,\n    customBlocks: Block[],\n    far: number\n  ) => {\n    this.collideCheck(Side.down, position, noise, customBlocks, far)\n    this.collideCheck(Side.front, position, noise, customBlocks)\n    this.collideCheck(Side.back, position, noise, customBlocks)\n    this.collideCheck(Side.left, position, noise, customBlocks)\n    this.collideCheck(Side.right, position, noise, customBlocks)\n    this.collideCheck(Side.up, position, noise, customBlocks)\n  }\n\n  collideCheck = (\n    side: Side,\n    position: THREE.Vector3,\n    noise: Noise,\n    customBlocks: Block[],\n    far: number = this.player.body.width\n  ) => {\n    const matrix = new THREE.Matrix4()\n\n    //reset simulation blocks\n    let index = 0\n    this.tempMesh.instanceMatrix = new THREE.InstancedBufferAttribute(\n      new Float32Array(100 * 16),\n      16\n    )\n\n    // block to remove\n    let removed = false\n    let treeRemoved = new Array<boolean>(\n      this.terrain.noise.treeHeight + 1\n    ).fill(false)\n\n    // get block position\n    let x = Math.round(position.x)\n    let z = Math.round(position.z)\n\n    switch (side) {\n      case Side.front:\n        x++\n        this.raycasterFront.ray.origin = position\n        break\n      case Side.back:\n        x--\n        this.raycasterBack.ray.origin = position\n        break\n      case Side.left:\n        z--\n        this.raycasterLeft.ray.origin = position\n        break\n      case Side.right:\n        z++\n        this.raycasterRight.ray.origin = position\n        break\n      case Side.down:\n        this.raycasterDown.ray.origin = position\n        this.raycasterDown.far = far\n        break\n      case Side.up:\n        this.raycasterUp.ray.origin = new THREE.Vector3().copy(position)\n        this.raycasterUp.ray.origin.y--\n        break\n    }\n\n    let y =\n      Math.floor(\n        noise.get(x / noise.gap, z / noise.gap, noise.seed) * noise.amp\n      ) + 30\n\n    // check custom blocks\n    for (const block of customBlocks) {\n      if (block.x === x && block.z === z) {\n        if (block.placed) {\n          // placed blocks\n          matrix.setPosition(block.x, block.y, block.z)\n          this.tempMesh.setMatrixAt(index++, matrix)\n        } else if (block.y === y) {\n          // removed blocks\n          removed = true\n        } else {\n          for (let i = 1; i <= this.terrain.noise.treeHeight; i++) {\n            if (block.y === y + i) {\n              treeRemoved[i] = true\n            }\n          }\n        }\n      }\n    }\n\n    // update simulation blocks (ignore removed blocks)\n    if (!removed) {\n      matrix.setPosition(x, y, z)\n      this.tempMesh.setMatrixAt(index++, matrix)\n    }\n    for (let i = 1; i <= this.terrain.noise.treeHeight; i++) {\n      if (!treeRemoved[i]) {\n        let treeOffset =\n          noise.get(x / noise.treeGap, z / noise.treeGap, noise.treeSeed) *\n          noise.treeAmp\n\n        let stoneOffset =\n          noise.get(x / noise.stoneGap, z / noise.stoneGap, noise.stoneSeed) *\n          noise.stoneAmp\n\n        if (\n          treeOffset > noise.treeThreshold &&\n          y >= 27 &&\n          stoneOffset < noise.stoneThreshold\n        ) {\n          matrix.setPosition(x, y + i, z)\n          this.tempMesh.setMatrixAt(index++, matrix)\n        }\n      }\n    }\n\n    this.tempMesh.instanceMatrix.needsUpdate = true\n\n    // update collide\n    const origin = new THREE.Vector3(position.x, position.y - 1, position.z)\n    switch (side) {\n      case Side.front: {\n        const c1 = this.raycasterFront.intersectObject(this.tempMesh).length\n        this.raycasterFront.ray.origin = origin\n        const c2 = this.raycasterFront.intersectObject(this.tempMesh).length\n        c1 || c2 ? (this.frontCollide = true) : (this.frontCollide = false)\n\n        break\n      }\n      case Side.back: {\n        const c1 = this.raycasterBack.intersectObject(this.tempMesh).length\n        this.raycasterBack.ray.origin = origin\n        const c2 = this.raycasterBack.intersectObject(this.tempMesh).length\n        c1 || c2 ? (this.backCollide = true) : (this.backCollide = false)\n        break\n      }\n      case Side.left: {\n        const c1 = this.raycasterLeft.intersectObject(this.tempMesh).length\n        this.raycasterLeft.ray.origin = origin\n        const c2 = this.raycasterLeft.intersectObject(this.tempMesh).length\n        c1 || c2 ? (this.leftCollide = true) : (this.leftCollide = false)\n        break\n      }\n      case Side.right: {\n        const c1 = this.raycasterRight.intersectObject(this.tempMesh).length\n        this.raycasterRight.ray.origin = origin\n        const c2 = this.raycasterRight.intersectObject(this.tempMesh).length\n        c1 || c2 ? (this.rightCollide = true) : (this.rightCollide = false)\n        break\n      }\n      case Side.down: {\n        const c1 = this.raycasterDown.intersectObject(this.tempMesh).length\n        c1 ? (this.downCollide = true) : (this.downCollide = false)\n        break\n      }\n      case Side.up: {\n        const c1 = this.raycasterUp.intersectObject(this.tempMesh).length\n        c1 ? (this.upCollide = true) : (this.upCollide = false)\n        break\n      }\n    }\n  }\n\n  update = () => {\n    this.p1 = performance.now()\n    const delta = (this.p1 - this.p2) / 1000\n    if (\n      // dev mode\n      this.player.mode === Mode.flying\n    ) {\n      this.control.moveForward(this.velocity.x * delta)\n      this.control.moveRight(this.velocity.z * delta)\n      this.camera.position.y += this.velocity.y * delta\n    } else {\n      // normal mode\n      this.collideCheckAll(\n        this.camera.position,\n        this.terrain.noise,\n        this.terrain.customBlocks,\n        this.far - this.velocity.y * delta\n      )\n\n      // gravity\n      if (Math.abs(this.velocity.y) < this.player.falling) {\n        this.velocity.y -= 25 * delta\n      }\n\n      // up collide handler\n      if (this.upCollide) {\n        this.velocity.y = -225 * delta\n        this.far = this.player.body.height\n      }\n\n      // down collide and jump handler\n      if (this.downCollide && !this.isJumping) {\n        this.velocity.y = 0\n      } else if (this.downCollide && this.isJumping) {\n        this.isJumping = false\n      }\n\n      // side collide handler\n      let vector = new THREE.Vector3(0, 0, -1).applyQuaternion(\n        this.camera.quaternion\n      )\n      let direction = Math.atan2(vector.x, vector.z)\n      if (\n        this.frontCollide ||\n        this.backCollide ||\n        this.leftCollide ||\n        this.rightCollide\n      ) {\n        // collide front (positive x)\n        if (this.frontCollide) {\n          // camera front\n          if (direction < Math.PI && direction > 0 && this.velocity.x > 0) {\n            if (\n              (!this.leftCollide && direction > Math.PI / 2) ||\n              (!this.rightCollide && direction < Math.PI / 2)\n            ) {\n              this.moveZ(Math.PI / 2 - direction, delta)\n            }\n          } else if (\n            !this.leftCollide &&\n            !this.rightCollide &&\n            this.velocity.x > 0\n          ) {\n            this.control.moveForward(this.velocity.x * delta)\n          }\n\n          // camera back\n          if (direction < 0 && direction > -Math.PI && this.velocity.x < 0) {\n            if (\n              (!this.leftCollide && direction > -Math.PI / 2) ||\n              (!this.rightCollide && direction < -Math.PI / 2)\n            ) {\n              this.moveZ(-Math.PI / 2 - direction, delta)\n            }\n          } else if (\n            !this.leftCollide &&\n            !this.rightCollide &&\n            this.velocity.x < 0\n          ) {\n            this.control.moveForward(this.velocity.x * delta)\n          }\n\n          // camera left\n          if (\n            direction < Math.PI / 2 &&\n            direction > -Math.PI / 2 &&\n            this.velocity.z < 0\n          ) {\n            if (\n              (!this.rightCollide && direction < 0) ||\n              (!this.leftCollide && direction > 0)\n            ) {\n              this.moveZ(-direction, delta)\n            }\n          } else if (\n            !this.leftCollide &&\n            !this.rightCollide &&\n            this.velocity.z < 0\n          ) {\n            this.control.moveRight(this.velocity.z * delta)\n          }\n\n          // camera right\n          if (\n            (direction < -Math.PI / 2 || direction > Math.PI / 2) &&\n            this.velocity.z > 0\n          ) {\n            if (!this.rightCollide && direction > 0) {\n              this.moveZ(Math.PI - direction, delta)\n            }\n            if (!this.leftCollide && direction < 0) {\n              this.moveZ(-Math.PI - direction, delta)\n            }\n          } else if (\n            !this.leftCollide &&\n            !this.rightCollide &&\n            this.velocity.z > 0\n          ) {\n            this.control.moveRight(this.velocity.z * delta)\n          }\n        }\n\n        // collide back (negative x)\n        if (this.backCollide) {\n          // camera front\n          if (direction < 0 && direction > -Math.PI && this.velocity.x > 0) {\n            if (\n              (!this.leftCollide && direction < -Math.PI / 2) ||\n              (!this.rightCollide && direction > -Math.PI / 2)\n            ) {\n              this.moveZ(Math.PI / 2 + direction, delta)\n            }\n          } else if (\n            !this.leftCollide &&\n            !this.rightCollide &&\n            this.velocity.x > 0\n          ) {\n            this.control.moveForward(this.velocity.x * delta)\n          }\n\n          // camera back\n          if (direction < Math.PI && direction > 0 && this.velocity.x < 0) {\n            if (\n              (!this.leftCollide && direction < Math.PI / 2) ||\n              (!this.rightCollide && direction > Math.PI / 2)\n            ) {\n              this.moveZ(direction - Math.PI / 2, delta)\n            }\n          } else if (\n            !this.leftCollide &&\n            !this.rightCollide &&\n            this.velocity.x < 0\n          ) {\n            this.control.moveForward(this.velocity.x * delta)\n          }\n\n          // camera left\n          if (\n            (direction < -Math.PI / 2 || direction > Math.PI / 2) &&\n            this.velocity.z < 0\n          ) {\n            if (!this.leftCollide && direction > 0) {\n              this.moveZ(-Math.PI + direction, delta)\n            }\n            if (!this.rightCollide && direction < 0) {\n              this.moveZ(Math.PI + direction, delta)\n            }\n          } else if (\n            !this.leftCollide &&\n            !this.rightCollide &&\n            this.velocity.z < 0\n          ) {\n            this.control.moveRight(this.velocity.z * delta)\n          }\n\n          // camera right\n          if (\n            direction < Math.PI / 2 &&\n            direction > -Math.PI / 2 &&\n            this.velocity.z > 0\n          ) {\n            if (\n              (!this.leftCollide && direction < 0) ||\n              (!this.rightCollide && direction > 0)\n            ) {\n              this.moveZ(direction, delta)\n            }\n          } else if (\n            !this.leftCollide &&\n            !this.rightCollide &&\n            this.velocity.z > 0\n          ) {\n            this.control.moveRight(this.velocity.z * delta)\n          }\n        }\n\n        // collide left (negative z)\n        if (this.leftCollide) {\n          // camera front\n          if (\n            (direction < -Math.PI / 2 || direction > Math.PI / 2) &&\n            this.velocity.x > 0\n          ) {\n            if (!this.frontCollide && direction > 0) {\n              this.moveX(Math.PI - direction, delta)\n            }\n            if (!this.backCollide && direction < 0) {\n              this.moveX(-Math.PI - direction, delta)\n            }\n          } else if (\n            !this.frontCollide &&\n            !this.backCollide &&\n            this.velocity.x > 0\n          ) {\n            this.control.moveForward(this.velocity.x * delta)\n          } else if (\n            this.frontCollide &&\n            direction < 0 &&\n            direction > -Math.PI / 2 &&\n            this.velocity.x > 0\n          ) {\n            this.control.moveForward(this.velocity.x * delta)\n          } else if (\n            this.backCollide &&\n            direction < Math.PI / 2 &&\n            direction > 0 &&\n            this.velocity.x > 0\n          ) {\n            this.control.moveForward(this.velocity.x * delta)\n          }\n\n          // camera back\n          if (\n            direction < Math.PI / 2 &&\n            direction > -Math.PI / 2 &&\n            this.velocity.x < 0\n          ) {\n            if (\n              (!this.frontCollide && direction < 0) ||\n              (!this.backCollide && direction > 0)\n            ) {\n              this.moveX(-direction, delta)\n            }\n          } else if (\n            !this.frontCollide &&\n            !this.backCollide &&\n            this.velocity.x < 0\n          ) {\n            this.control.moveForward(this.velocity.x * delta)\n          } else if (\n            this.frontCollide &&\n            direction < Math.PI &&\n            direction > Math.PI / 2 &&\n            this.velocity.x < 0\n          ) {\n            this.control.moveForward(this.velocity.x * delta)\n          } else if (\n            this.backCollide &&\n            direction > -Math.PI &&\n            direction < -Math.PI / 2 &&\n            this.velocity.x < 0\n          ) {\n            this.control.moveForward(this.velocity.x * delta)\n          }\n\n          // camera left\n          if (direction > 0 && direction < Math.PI && this.velocity.z < 0) {\n            if (\n              (!this.backCollide && direction > Math.PI / 2) ||\n              (!this.frontCollide && direction < Math.PI / 2)\n            ) {\n              this.moveX(Math.PI / 2 - direction, delta)\n            }\n          } else if (\n            !this.frontCollide &&\n            !this.backCollide &&\n            this.velocity.z < 0\n          ) {\n            this.control.moveRight(this.velocity.z * delta)\n          } else if (\n            this.frontCollide &&\n            direction > -Math.PI &&\n            direction < -Math.PI / 2 &&\n            this.velocity.z < 0\n          ) {\n            this.control.moveRight(this.velocity.z * delta)\n          } else if (\n            this.backCollide &&\n            direction > -Math.PI / 2 &&\n            direction < 0 &&\n            this.velocity.z < 0\n          ) {\n            this.control.moveRight(this.velocity.z * delta)\n          }\n\n          // camera right\n          if (direction < 0 && direction > -Math.PI && this.velocity.z > 0) {\n            if (\n              (!this.backCollide && direction > -Math.PI / 2) ||\n              (!this.frontCollide && direction < -Math.PI / 2)\n            ) {\n              this.moveX(-Math.PI / 2 - direction, delta)\n            }\n          } else if (\n            !this.frontCollide &&\n            !this.backCollide &&\n            this.velocity.z > 0\n          ) {\n            this.control.moveRight(this.velocity.z * delta)\n          } else if (\n            this.frontCollide &&\n            direction < Math.PI / 2 &&\n            direction > 0 &&\n            this.velocity.z > 0\n          ) {\n            this.control.moveRight(this.velocity.z * delta)\n          } else if (\n            this.backCollide &&\n            direction < Math.PI &&\n            direction > Math.PI / 2 &&\n            this.velocity.z > 0\n          ) {\n            this.control.moveRight(this.velocity.z * delta)\n          }\n        }\n\n        // collide right (positive z)\n        if (this.rightCollide) {\n          // camera front\n          if (\n            direction < Math.PI / 2 &&\n            direction > -Math.PI / 2 &&\n            this.velocity.x > 0\n          ) {\n            if (\n              (!this.backCollide && direction < 0) ||\n              (!this.frontCollide && direction > 0)\n            ) {\n              this.moveX(direction, delta)\n            }\n          } else if (\n            !this.frontCollide &&\n            !this.backCollide &&\n            this.velocity.x > 0\n          ) {\n            this.control.moveForward(this.velocity.x * delta)\n          } else if (\n            this.frontCollide &&\n            direction < -Math.PI / 2 &&\n            direction > -Math.PI &&\n            this.velocity.x > 0\n          ) {\n            this.control.moveForward(this.velocity.x * delta)\n          } else if (\n            this.backCollide &&\n            direction < Math.PI &&\n            direction > Math.PI / 2 &&\n            this.velocity.x > 0\n          ) {\n            this.control.moveForward(this.velocity.x * delta)\n          }\n\n          // camera back\n          if (\n            (direction < -Math.PI / 2 || direction > Math.PI / 2) &&\n            this.velocity.x < 0\n          ) {\n            if (!this.backCollide && direction > 0) {\n              this.moveX(-Math.PI + direction, delta)\n            }\n            if (!this.frontCollide && direction < 0) {\n              this.moveX(Math.PI + direction, delta)\n            }\n          } else if (\n            !this.frontCollide &&\n            !this.backCollide &&\n            this.velocity.x < 0\n          ) {\n            this.control.moveForward(this.velocity.x * delta)\n          } else if (\n            this.frontCollide &&\n            direction < Math.PI / 2 &&\n            direction > 0 &&\n            this.velocity.x < 0\n          ) {\n            this.control.moveForward(this.velocity.x * delta)\n          } else if (\n            this.backCollide &&\n            direction < 0 &&\n            direction > -Math.PI / 2 &&\n            this.velocity.x < 0\n          ) {\n            this.control.moveForward(this.velocity.x * delta)\n          }\n\n          // camera left\n          if (direction < 0 && direction > -Math.PI && this.velocity.z < 0) {\n            if (\n              (!this.frontCollide && direction > -Math.PI / 2) ||\n              (!this.backCollide && direction < -Math.PI / 2)\n            ) {\n              this.moveX(Math.PI / 2 + direction, delta)\n            }\n          } else if (\n            !this.frontCollide &&\n            !this.backCollide &&\n            this.velocity.z < 0\n          ) {\n            this.control.moveRight(this.velocity.z * delta)\n          } else if (\n            this.frontCollide &&\n            direction > Math.PI / 2 &&\n            direction < Math.PI &&\n            this.velocity.z < 0\n          ) {\n            this.control.moveRight(this.velocity.z * delta)\n          } else if (\n            this.backCollide &&\n            direction > 0 &&\n            direction < Math.PI / 2 &&\n            this.velocity.z < 0\n          ) {\n            this.control.moveRight(this.velocity.z * delta)\n          }\n\n          // camera right\n          if (direction > 0 && direction < Math.PI && this.velocity.z > 0) {\n            if (\n              (!this.frontCollide && direction > Math.PI / 2) ||\n              (!this.backCollide && direction < Math.PI / 2)\n            ) {\n              this.moveX(direction - Math.PI / 2, delta)\n            }\n          } else if (\n            !this.frontCollide &&\n            !this.backCollide &&\n            this.velocity.z > 0\n          ) {\n            this.control.moveRight(this.velocity.z * delta)\n          } else if (\n            this.frontCollide &&\n            direction > -Math.PI / 2 &&\n            direction < 0 &&\n            this.velocity.z > 0\n          ) {\n            this.control.moveRight(this.velocity.z * delta)\n          } else if (\n            this.backCollide &&\n            direction > -Math.PI &&\n            direction < -Math.PI / 2 &&\n            this.velocity.z > 0\n          ) {\n            this.control.moveRight(this.velocity.z * delta)\n          }\n        }\n      } else {\n        // no collide\n        this.control.moveForward(this.velocity.x * delta)\n        this.control.moveRight(this.velocity.z * delta)\n      }\n\n      this.camera.position.y += this.velocity.y * delta\n\n      // catching net\n      if (this.camera.position.y < -100) {\n        this.camera.position.y = 60\n      }\n    }\n    this.p2 = this.p1\n  }\n}\n","/**\n * Display current FPS\n */\nexport default class FPS {\n  constructor() {\n    this.fps.className = 'fps'\n    this.fps.innerHTML = `FPS: 60`\n\n    document.body.appendChild(this.fps)\n  }\n\n  p1 = performance.now()\n  p2 = performance.now()\n  gap = performance.now()\n  fps = document.createElement('div')\n  count = 0\n\n  update = () => {\n    this.p1 = performance.now()\n    this.count++\n\n    if (performance.now() - this.gap > 1000) {\n      this.fps.innerHTML = `FPS: ${this.count}`\n      this.gap = performance.now()\n      this.count = 0\n    }\n\n    this.p2 = this.p1\n  }\n}\n","export default \"__VITE_ASSET__020eb145__\"","export default \"__VITE_ASSET__53e38748__\"","export default \"__VITE_ASSET__98a9b0d4__\"","export default \"__VITE_ASSET__9768871f__\"","export default \"__VITE_ASSET__b6171099__\"","export default \"__VITE_ASSET__9ffd1d51__\"","export default \"__VITE_ASSET__3e48b289__\"","import grass from '../../static/block-icon/grass.png'\nimport stone from '../../static/block-icon/stone.png'\nimport tree from '../../static/block-icon/tree.png'\nimport wood from '../../static/block-icon/wood.png'\nimport diamond from '../../static/block-icon/diamond.png'\nimport quartz from '../../static/block-icon/quartz.png'\nimport glass from '../../static/block-icon/glass.png'\nimport { isMobile } from '../../utils'\n\nexport default class Bag {\n  constructor() {\n    if (isMobile) return\n\n    this.bag.className = 'bag'\n    this.items[0].classList.add('selected')\n\n    for (let i = 0; i < this.items.length; i++) {\n      this.bag.appendChild(this.items[i])\n    }\n    document.body.appendChild(this.bag)\n\n    document.body.addEventListener('keydown', (e: KeyboardEvent) => {\n      if (isNaN(parseInt(e.key)) || e.key === '0') {\n        return\n      }\n\n      for (let i = 0; i < this.items.length; i++) {\n        this.items[i].classList.remove('selected')\n      }\n\n      this.current = parseInt(e.key) - 1\n      this.items[this.current].classList.add('selected')\n    })\n\n    document.body.addEventListener('wheel', (e: WheelEvent) => {\n      if (!this.wheelGap) {\n        this.wheelGap = true\n        setTimeout(() => {\n          this.wheelGap = false\n        }, 100)\n        if (e.deltaY > 0) {\n          this.current++\n          this.current > 9 && (this.current = 0)\n        } else if (e.deltaY < 0) {\n          this.current--\n          this.current < 0 && (this.current = 9)\n        }\n        for (let i = 0; i < this.items.length; i++) {\n          this.items[i].classList.remove('selected')\n        }\n        this.items[this.current].classList.add('selected')\n      }\n    })\n  }\n  wheelGap = false\n  current = 0\n  icon = [grass, stone, tree, wood, diamond, quartz, glass]\n  iconIndex = 0\n  y = 0\n\n  bag = document.createElement('div')\n\n  items = new Array(10).fill(null).map(() => {\n    let item = document.createElement('div')\n    item.className = 'item'\n\n    let img = document.createElement('img')\n    if (this.icon[this.iconIndex]) {\n      img.className = 'icon'\n      img.alt = 'block'\n      img.src = this.icon[this.iconIndex++]\n      item.appendChild(img)\n    }\n\n    return item\n  })\n}\n","export default \"<div class=\\\"joystick\\\">\\n  <button id=\\\"action-front\\\" class=\\\"joystick-button front\\\" role=\\\"div\\\">🔼</button>\\n  <button id=\\\"action-left\\\" class=\\\"joystick-button left\\\" role=\\\"div\\\">◀️</button>\\n  <button id=\\\"action-right\\\" class=\\\"joystick-button right\\\" role=\\\"div\\\">▶️</button>\\n  <button id=\\\"action-back\\\" class=\\\"joystick-button back\\\" role=\\\"div\\\">🔽</button>\\n  <button id=\\\"action-mode\\\" class=\\\"joystick-button mode\\\" role=\\\"div\\\">⏹️</button>\\n  <button id=\\\"action-up\\\" class=\\\"joystick-button up\\\" role=\\\"div\\\">🔼</button>\\n  <button id=\\\"action-down\\\" class=\\\"joystick-button down hidden\\\" role=\\\"div\\\">\\n    🔽\\n  </button>\\n</div>\\n\\n<style>\\n  .joystick {\\n    position: fixed;\\n    bottom: 0;\\n    display: grid;\\n    width: 100%;\\n    grid-template-columns: repeat(auto-fill, 50px);\\n    grid-template-rows: repeat(3, 1fr);\\n    gap: 10px;\\n    padding: 10px;\\n  }\\n  .joystick-button {\\n    width: 52px;\\n    height: 50px;\\n    font-size: 50px;\\n    line-height: 50px;\\n    padding: 0px;\\n    border: none;\\n    background-color: transparent;\\n  }\\n  .front {\\n    grid-column: 2 / 3;\\n    grid-row: 1;\\n  }\\n  .left {\\n    grid-column: 1 / 2;\\n    grid-row: 2;\\n  }\\n  .right {\\n    grid-column: 3 / 4;\\n    grid-row: 2;\\n  }\\n  .back {\\n    grid-column: 2 / 3;\\n    grid-row: 3;\\n  }\\n  .mode {\\n    grid-column: 2 / 3;\\n    grid-row: 2;\\n  }\\n  .up {\\n    grid-column: -3 / -2;\\n    grid-row: 2;\\n  }\\n  .down {\\n    grid-column: -3 / -2;\\n    grid-row: 3;\\n  }\\n</style>\\n\"","import * as THREE from 'three'\nimport Control from '../../control'\nimport { Mode } from '../../player'\nimport { htmlToDom } from '../../utils'\nimport UI from './joystick.html?raw'\n\nenum ActionKey {\n  FRONT = 'front',\n  LEFT = 'left',\n  RIGHT = 'right',\n  BACK = 'back',\n  MODE = 'mode',\n  JUMP = 'jump',\n  UP = 'up',\n  DOWN = 'down'\n}\n\nexport default class Joystick {\n  constructor(control: Control) {\n    this.control = control\n    this.euler = new THREE.Euler(0, 0, 0, 'YXZ')\n  }\n\n  control: Control\n  pageX = 0\n  pageY = 0\n  clickX = 0\n  clickY = 0\n  euler: THREE.Euler\n  clickTimeout?: ReturnType<typeof setTimeout>\n  clickInterval?: ReturnType<typeof setInterval>\n  hold = false\n\n  // emit keyboard event\n  private emitKeyboardEvent = (key: string) => {\n    return {\n      key\n    } as KeyboardEvent\n  }\n\n  // emit click event\n  private emitClickEvent = (button: number) => {\n    return {\n      button,\n      preventDefault: () => { }\n    } as MouseEvent\n  }\n\n  // init joystick button\n  private initButton = ({\n    actionKey,\n    key\n  }: {\n    actionKey: ActionKey\n    key: string\n  }) => {\n    const button = document.querySelector(\n      `#action-${actionKey}`\n    ) as HTMLButtonElement\n    button.addEventListener('pointermove', e => {\n      e.stopPropagation()\n    })\n    button.addEventListener('pointerdown', e => {\n      this.control.setMovementHandler(this.emitKeyboardEvent(key))\n      e.stopPropagation()\n    })\n    button.addEventListener('pointerup', e => {\n      this.control.resetMovementHandler(this.emitKeyboardEvent(key))\n      e.stopPropagation()\n    })\n    // extra config for mode switch button\n    if (actionKey === ActionKey.MODE && key === 'q') {\n      this.initButton({ actionKey: ActionKey.MODE, key: ' ' })\n      button.addEventListener('pointerdown', () => {\n        if (this.control.player.mode === Mode.flying) {\n          document.querySelector('#action-down')?.classList.remove('hidden')\n        } else {\n          document.querySelector('#action-down')?.classList.add('hidden')\n        }\n      })\n    }\n  }\n\n  init = () => {\n    htmlToDom(UI)\n\n    this.initButton({ actionKey: ActionKey.FRONT, key: 'w' })\n    this.initButton({ actionKey: ActionKey.LEFT, key: 'a' })\n    this.initButton({ actionKey: ActionKey.RIGHT, key: 'd' })\n    this.initButton({ actionKey: ActionKey.BACK, key: 's' })\n    this.initButton({ actionKey: ActionKey.MODE, key: 'q' })\n    this.initButton({ actionKey: ActionKey.UP, key: ' ' })\n    this.initButton({ actionKey: ActionKey.DOWN, key: 'Shift' })\n\n    // camera control\n    document.addEventListener('pointermove', e => {\n      if (this.pageX !== 0 || this.pageY !== 0) {\n        this.euler.setFromQuaternion(this.control.camera.quaternion)\n        this.euler.y -= 0.01 * (e.pageX - this.pageX)\n        this.euler.x -= 0.01 * (e.pageY - this.pageY)\n        this.euler.x = Math.max(\n          -Math.PI / 2,\n          Math.min(Math.PI / 2, this.euler.x)\n        )\n        this.control.camera.quaternion.setFromEuler(this.euler)\n      }\n      this.pageX = e.pageX\n      this.pageY = e.pageY\n      this.clickTimeout && clearTimeout(this.clickTimeout)\n    })\n\n    // click control\n    document.addEventListener('pointerdown', e => {\n      this.clickX = e.pageX\n      this.clickY = e.pageY\n\n      this.clickTimeout = setTimeout(() => {\n        if (e.pageX === this.clickX && e.pageY === this.clickY) {\n          this.control.mousedownHandler(this.emitClickEvent(0))\n          this.clickInterval = setInterval(() => {\n            this.control.mousedownHandler(this.emitClickEvent(0))\n          }, 333)\n          this.hold = true\n        }\n      }, 500)\n    })\n\n    document.addEventListener('pointerup', e => {\n      this.clickTimeout && clearTimeout(this.clickTimeout)\n      this.clickInterval && clearInterval(this.clickInterval)\n\n      if (!this.hold && e.pageX === this.clickX && e.pageY === this.clickY) {\n        this.control.mousedownHandler(this.emitClickEvent(2))\n      }\n      this.hold = false\n      this.pageX = 0\n      this.pageY = 0\n    })\n  }\n}\n","import FPS from './fps'\nimport Bag from './bag'\nimport Terrain from '../terrain'\nimport Block from '../terrain/mesh/block'\nimport Control from '../control'\nimport { Mode } from '../player'\nimport Joystick from './joystick'\nimport { isMobile } from '../utils'\nimport * as THREE from 'three'\n\nexport default class UI {\n  constructor(terrain: Terrain, control: Control) {\n    this.fps = new FPS()\n    this.bag = new Bag()\n    this.joystick = new Joystick(control)\n\n    this.crossHair.className = 'cross-hair'\n    this.crossHair.innerHTML = '+'\n    document.body.appendChild(this.crossHair)\n\n    // play\n    this.play?.addEventListener('click', () => {\n      if (this.play?.innerHTML === 'Play') {\n        this.onPlay()\n\n        // reset game\n        terrain.noise.seed = Math.random()\n        terrain.noise.stoneSeed = Math.random()\n        terrain.noise.treeSeed = Math.random()\n        terrain.noise.coalSeed = Math.random()\n        terrain.noise.leafSeed = Math.random()\n        terrain.customBlocks = []\n        terrain.initBlocks()\n        terrain.generate()\n        terrain.camera.position.y = 40\n        control.player.setMode(Mode.walking)\n      }\n      !isMobile && control.control.lock()\n    })\n\n    // save load\n    this.save?.addEventListener('click', () => {\n      if (this.save?.innerHTML === 'Save and Exit') {\n        // save game\n        window.localStorage.setItem(\n          'block',\n          JSON.stringify(terrain.customBlocks)\n        )\n        window.localStorage.setItem('seed', JSON.stringify(terrain.noise.seed))\n\n        window.localStorage.setItem(\n          'position',\n          JSON.stringify({\n            x: terrain.camera.position.x,\n            y: terrain.camera.position.y,\n            z: terrain.camera.position.z\n          })\n        )\n\n        // ui update\n        this.onExit()\n        this.onSave()\n      } else {\n        // load game\n        terrain.noise.seed =\n          Number(window.localStorage.getItem('seed')) ?? Math.random()\n\n        const customBlocks =\n          (JSON.parse(\n            window.localStorage.getItem('block') || 'null'\n          ) as Block[]) ?? []\n\n        terrain.customBlocks = customBlocks\n        terrain.initBlocks()\n        terrain.generate()\n\n        const position =\n          (JSON.parse(window.localStorage.getItem('position') || 'null') as {\n            x: number\n            y: number\n            z: number\n          }) ?? null\n\n        position && (terrain.camera.position.x = position.x)\n        position && (terrain.camera.position.y = position.y)\n        position && (terrain.camera.position.z = position.z)\n\n        // ui update\n        this.onPlay()\n        this.onLoad()\n        !isMobile && control.control.lock()\n      }\n    })\n\n    // guide\n    this.feature?.addEventListener('click', () => {\n      this.features?.classList.remove('hidden')\n    })\n    this.back?.addEventListener('click', () => {\n      this.features?.classList.add('hidden')\n    })\n\n    // setting\n    this.setting?.addEventListener('click', () => {\n      this.settings?.classList.remove('hidden')\n    })\n    this.settingBack?.addEventListener('click', () => {\n      this.settings?.classList.add('hidden')\n    })\n\n    // render distance\n    this.distanceInput?.addEventListener('input', (e: Event) => {\n      if (this.distance && e.target instanceof HTMLInputElement) {\n        this.distance.innerHTML = `Render Distance: ${e.target.value}`\n      }\n    })\n\n    // fov\n    this.fovInput?.addEventListener('input', (e: Event) => {\n      if (this.fov && e.target instanceof HTMLInputElement) {\n        this.fov.innerHTML = `Field of View: ${e.target.value}`\n        control.camera.fov = parseInt(e.target.value)\n        control.camera.updateProjectionMatrix()\n      }\n    })\n\n    // music\n    this.musicInput?.addEventListener('input', (e: Event) => {\n      if (this.fov && e.target instanceof HTMLInputElement) {\n        const disabled = e.target.value === '0'\n        control.audio.disabled = disabled\n        this.music!.innerHTML = `Music: ${disabled ? 'Off' : 'On'}`\n      }\n    })\n\n    // apply settings\n    this.settingBack?.addEventListener('click', () => {\n      if (this.distanceInput instanceof HTMLInputElement) {\n        terrain.distance = parseInt(this.distanceInput.value)\n        terrain.maxCount =\n          (terrain.distance * terrain.chunkSize * 2 + terrain.chunkSize) ** 2 +\n          500\n\n        terrain.initBlocks()\n        terrain.generate()\n        terrain.scene.fog = new THREE.Fog(\n          0x87ceeb,\n          1,\n          terrain.distance * 24 + 24\n        )\n      }\n    })\n\n    // menu and fullscreen\n    document.body.addEventListener('keydown', (e: KeyboardEvent) => {\n      // menu\n      if (e.key === 'e' && document.pointerLockElement) {\n        !isMobile && control.control.unlock()\n      }\n\n      // fullscreen\n      if (e.key === 'f') {\n        if (document.fullscreenElement) {\n          document.exitFullscreen()\n        } else {\n          document.body.requestFullscreen()\n        }\n      }\n    })\n\n    // exit\n    this.exit?.addEventListener('click', () => {\n      this.onExit()\n    })\n\n    // play / pause handler\n    document.addEventListener('pointerlockchange', () => {\n      if (document.pointerLockElement) {\n        this.onPlay()\n      } else {\n        this.onPause()\n      }\n    })\n\n    // disable context menu\n    document.addEventListener('contextmenu', e => {\n      e.preventDefault()\n    })\n\n    // fallback lock handler\n    document.querySelector('canvas')?.addEventListener('click', (e: Event) => {\n      e.preventDefault()\n      !isMobile && control.control.lock()\n    })\n  }\n\n  fps: FPS\n  bag: Bag\n  joystick: Joystick\n\n  menu = document.querySelector('.menu')\n  crossHair = document.createElement('div')\n\n  // buttons\n  play = document.querySelector('#play')\n  control = document.querySelector('#control')\n  setting = document.querySelector('#setting')\n  feature = document.querySelector('#feature')\n  back = document.querySelector('#back')\n  exit = document.querySelector('#exit')\n  save = document.querySelector('#save')\n\n  // modals\n  saveModal = document.querySelector('.save-modal')\n  loadModal = document.querySelector('.load-modal')\n  settings = document.querySelector('.settings')\n  features = document.querySelector('.features')\n  github = document.querySelector('.github')\n\n  // settings\n  distance = document.querySelector('#distance')\n  distanceInput = document.querySelector('#distance-input')\n\n  fov = document.querySelector('#fov')\n  fovInput = document.querySelector('#fov-input')\n\n  music = document.querySelector('#music')\n  musicInput = document.querySelector('#music-input')\n\n  settingBack = document.querySelector('#setting-back')\n\n  onPlay = () => {\n    isMobile && this.joystick.init()\n    this.menu?.classList.add('hidden')\n    this.menu?.classList.remove('start')\n    this.play && (this.play.innerHTML = 'Resume')\n    this.crossHair.classList.remove('hidden')\n    this.github && this.github.classList.add('hidden')\n    this.feature?.classList.add('hidden')\n  }\n\n  onPause = () => {\n    this.menu?.classList.remove('hidden')\n    this.crossHair.classList.add('hidden')\n    this.save && (this.save.innerHTML = 'Save and Exit')\n    this.github && this.github.classList.remove('hidden')\n  }\n\n  onExit = () => {\n    this.menu?.classList.add('start')\n    this.play && (this.play.innerHTML = 'Play')\n    this.save && (this.save.innerHTML = 'Load Game')\n    this.feature?.classList.remove('hidden')\n  }\n\n  onSave = () => {\n    this.saveModal?.classList.remove('hidden')\n    setTimeout(() => {\n      this.saveModal?.classList.add('show')\n    })\n    setTimeout(() => {\n      this.saveModal?.classList.remove('show')\n    }, 1000)\n\n    setTimeout(() => {\n      this.saveModal?.classList.add('hidden')\n    }, 1350)\n  }\n\n  onLoad = () => {\n    this.loadModal?.classList.remove('hidden')\n    setTimeout(() => {\n      this.loadModal?.classList.add('show')\n    })\n    setTimeout(() => {\n      this.loadModal?.classList.remove('show')\n    }, 1000)\n\n    setTimeout(() => {\n      this.loadModal?.classList.add('hidden')\n    }, 1350)\n  }\n\n  update = () => {\n    this.fps.update()\n  }\n}\n","export default \"__VITE_ASSET__2642662e__\"","export default \"__VITE_ASSET__3619fdb8__\"","export default \"__VITE_ASSET__b0763cf2__\"","export default \"__VITE_ASSET__9ac02803__\"","export default \"__VITE_ASSET__dd733357__\"","export default \"__VITE_ASSET__1260ef32__\"","export default \"__VITE_ASSET__74ef2fa1__\"","export default \"__VITE_ASSET__0441e996__\"","export default \"__VITE_ASSET__42ac9116__\"","export default \"__VITE_ASSET__97f2a8a7__\"","export default \"__VITE_ASSET__98a5c319__\"","export default \"__VITE_ASSET__19273f0e__\"","export default \"__VITE_ASSET__b164e732__\"","export default \"__VITE_ASSET__55a610c8__\"","export default \"__VITE_ASSET__60ebf0ed__\"","export default \"__VITE_ASSET__ab5e4b40__\"","export default \"__VITE_ASSET__fd4aa755__\"","export default \"__VITE_ASSET__cb6071c8__\"","export default \"__VITE_ASSET__59edca84__\"","export default \"__VITE_ASSET__cf6be231__\"","export default \"__VITE_ASSET__de868b31__\"","export default \"__VITE_ASSET__74400cfe__\"","export default \"__VITE_ASSET__b7636085__\"","export default \"__VITE_ASSET__6228533c__\"","export default \"__VITE_ASSET__72db3634__\"","import * as THREE from 'three'\nimport hal3 from './musics/hal3.ogg'\nimport { BlockType } from '../terrain'\n\nimport grass1 from './blocks/grass1.ogg'\nimport grass2 from './blocks/grass2.ogg'\nimport grass3 from './blocks/grass3.ogg'\nimport grass4 from './blocks/grass4.ogg'\n\nimport sand1 from './blocks/sand1.ogg'\nimport sand2 from './blocks/sand2.ogg'\nimport sand3 from './blocks/sand3.ogg'\nimport sand4 from './blocks/sand4.ogg'\n\nimport stone1 from './blocks/stone1.ogg'\nimport stone2 from './blocks/stone2.ogg'\nimport stone3 from './blocks/stone3.ogg'\nimport stone4 from './blocks/stone4.ogg'\n\nimport dirt1 from './blocks/dirt1.ogg'\nimport dirt2 from './blocks/dirt2.ogg'\nimport dirt3 from './blocks/dirt3.ogg'\nimport dirt4 from './blocks/dirt4.ogg'\n\nimport tree1 from './blocks/tree1.ogg'\nimport tree2 from './blocks/tree2.ogg'\nimport tree3 from './blocks/tree3.ogg'\nimport tree4 from './blocks/tree4.ogg'\n\nimport leaf1 from './blocks/leaf1.ogg'\nimport leaf2 from './blocks/leaf2.ogg'\nimport leaf3 from './blocks/leaf3.ogg'\nimport leaf4 from './blocks/leaf4.ogg'\nimport { isMobile } from '../utils'\n\nexport default class Audio {\n  constructor(camera: THREE.PerspectiveCamera) {\n    if (isMobile) return\n\n    const listener = new THREE.AudioListener()\n    const audioLoader = new THREE.AudioLoader()\n    camera.add(listener)\n\n    // load bgm\n    const bgm = new THREE.Audio(listener)\n    bgm.autoplay = false\n    audioLoader.load(hal3, buffer => {\n      bgm.setBuffer(buffer)\n      bgm.setVolume(0.1)\n      bgm.setLoop(true)\n      if (bgm.isPlaying) {\n        bgm.pause()\n        bgm.play()\n      }\n    })\n\n    // play / pause bgm\n    document.addEventListener('pointerlockchange', () => {\n      if (document.pointerLockElement && !bgm.isPlaying && !this.disabled) {\n        bgm.play()\n      } else {\n        bgm.pause()\n      }\n    })\n\n    // load sound effect\n    for (const types of this.sourceSet) {\n      const audios: THREE.Audio[] = []\n      for (const type of types) {\n        audioLoader.load(type, buffer => {\n          const audio = new THREE.Audio(listener!)\n          audio.setBuffer(buffer)\n          audio.setVolume(0.15)\n          audios.push(audio)\n        })\n      }\n      this.soundSet.push(audios)\n    }\n  }\n\n  disabled = false\n\n  sourceSet = [\n    [grass1, grass2, grass3, grass4],\n    [sand1, sand2, sand3, sand4],\n    [tree1, tree2, tree3, tree4],\n    [leaf1, leaf2, leaf3, leaf4],\n    [dirt1, dirt2, dirt3, dirt4],\n    [stone1, stone2, stone3, stone4],\n    [stone1, stone2, stone3, stone4],\n    [tree1, tree2, tree3, tree4],\n    [stone1, stone2, stone3, stone4],\n    [stone1, stone2, stone3, stone4],\n    [stone1, stone2, stone3, stone4]\n  ]\n\n  soundSet: THREE.Audio[][] = []\n\n  index = 0\n\n  playSound(type: BlockType) {\n    if (!this.disabled && !isMobile) {\n      this.index++ === 3 && (this.index = 0)\n      this.soundSet[type]?.[this.index]?.play()\n    }\n  }\n}\n","import Core from './core'\nimport Control from './control'\nimport Player from './player'\nimport Terrain from './terrain'\nimport UI from './ui'\nimport Audio from './audio'\n\nimport './style.css'\n\nconst core = new Core()\nconst camera = core.camera\nconst scene = core.scene\nconst renderer = core.renderer\n\nconst player = new Player()\nconst audio = new Audio(camera)\n\nconst terrain = new Terrain(scene, camera)\nconst control = new Control(scene, camera, player, terrain, audio)\n\nconst ui = new UI(terrain, control)\n\n// animation\n;(function animate() {\n  // let p1 = performance.now()\n  requestAnimationFrame(animate)\n\n  control.update()\n  terrain.update()\n  ui.update()\n\n  renderer.render(scene, camera)\n  // console.log(performance.now()-p1)\n})()\n"],"names":["THREE.Scene","THREE.Fog","THREE.Color","THREE.PointLight","THREE.AmbientLight","THREE.PerspectiveCamera","THREE.WebGLRenderer","THREE.TextureLoader","stone","diamond","quartz","glass","THREE.NearestFilter","THREE.MeshStandardMaterial","THREE.BoxGeometry","THREE.Mesh","THREE.InstancedMesh","THREE.MeshBasicMaterial","THREE.Raycaster","THREE.InstancedBufferAttribute","THREE.Matrix4","THREE.Vector3","THREE.Vector2","Generate","Highlight","UI","THREE.Euler","THREE.AudioListener","THREE.AudioLoader","THREE.Audio"],"mappings":"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"}