UPDATE

上级 649065bb
"use strict";
const s = "\u6B22\u8FCE\u6765\u5230 InsCode";
console.log(s);
//# sourceMappingURL=index.js.map
{
"version": 3,
"sources": ["../index.ts"],
"sourcesContent": ["const s: string = \"\u6B22\u8FCE\u6765\u5230 InsCode\";\nconsole.log(s);\n"],
"mappings": ";AAAA,MAAM,IAAY;AAClB,QAAQ,IAAI,CAAC;",
"names": []
}
#!/usr/bin/env bash
set -e
rm -rf .build
mkdir -p ./.build
ENTRYPOINTS=$(find -type f -name '*.[tj]s' -not -path './node_modules/*')
esbuild $ENTRYPOINTS \
--log-level=warning \
--outdir='./.build' \
--outbase=. \
--sourcemap \
--target='node16' \
--platform='node' \
--format='cjs'
node_modules
.DS_Store
dist
dist-ssr
*.local
*-lock.yaml
run = "node --enable-source-maps .build/index.js" run = "upm add guess;npm run dev"
entrypoint = "index.ts" entrypoint = "index.ts"
[nix] [nix]
......
{"version":2,"languages":{"nodejs-yarn":{"specfileHash":"abab35c9ba66256c189aa42c5e29aa02","lockfileHash":"b4fe953f33f9be5c0086b24be0e7aad5"}}}
MIT License
Copyright (c) 2022 Vyse12138
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
# minecraft-threejs
English | [中文](https://github.com/vyse12138/minecraft-threejs/blob/main/README_ZH.md)
Minecraft clone made with Three.js and TypeScript
Check it out: [Minecraft - Three.js](https://mc.yulei.me/)
Recommend to use Chrome to get the best experience
![preview](https://user-images.githubusercontent.com/88306344/154383952-9b33bad4-eebb-4a98-a12e-f5f137422d06.gif)
## Features:
- Destroy block and place block
- Mouse wheel (or number key) to select different block types
- Movement and collision detection
- Random terrain / blocks / tree generations
- Infinite world
- Game save / load
- Sound effect and BGM
- Highlight the block at crosshair
- Basic UI and settings
- Mobile friendly
## Working on:
- Multiplayer
- Generates water
- Higher performance algorithm
# minecraft-threejs
中文 | [English](https://github.com/vyse12138/minecraft-threejs)
基于 Three.js 和 TypeScript 的网页版我的世界
试玩:[Minecraft - Three.js](https://mcz.yulei.me)
建议使用 Chrome 来获得最佳的体验
![preview](https://user-images.githubusercontent.com/88306344/154383952-9b33bad4-eebb-4a98-a12e-f5f137422d06.gif)
## 已支持:
- 方块的放置 / 破坏
- 鼠标滚轮(数字键)选择不同的方块类型
- 移动和碰撞检测
- 随机的地形和树木生成
- 无限的世界
- 保存 / 读取游戏
- 音效和背景音乐
- 可调节的渲染距离和视野范围
- 高亮准心方块
- 基本的 UI
- 支持桌面以及手机试玩
## 开发中:
- 更高效的算法(时间切片渲染算法和方块放置 / 破坏算法)
- 生成水
- 联机模式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/src/static/mc.ico" />
<meta
name="viewport"
content="width=device-width,initial-scale=1,maximum-scale=1"
/>
<meta
name="description"
content="Minecraft clone made with Three.js + TypeScript, play minecraft in your own browser!"
/>
<title>Minecraft - Three.js</title>
</head>
<body>
<script type="module" src="./src/main.ts"></script>
<a
href="https://github.com/Vyse12138/minecraft-threejs"
title="Source on GitHub"
class="github"
target="_blank"
rel="noopener"
>
<svg width="72" height="72" viewBox="0 0 250 250">
<path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path>
<path
d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2"
fill="white"
></path>
<path
d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z"
fill="white"
></path>
</svg>
</a>
<div class="menu start">
<button id="play" class="button">Play</button>
<button id="save" class="button">Load Game</button>
<button id="setting" class="button">Setting</button>
<button id="feature" class="button">Guide</button>
<button id="exit" class="button">Exit</button>
<footer class="footer">© 2022 Yulei Zhu</footer>
</div>
<div class="features hidden">
<p>
<b> Left-Click: </b> destroy block <br />
<b> Right-Click:</b> place block <br />
<b> Wheel / Number Key: </b>change block <br />
<b> WASD: </b>move <br />
<b> Space: </b>jump <br />
<b> Q:</b> normal / dev mode <br />
<b> Shift:</b> fly up (in dev mode) <br />
<b> F: </b>full screen <br />
<b> E: </b>menu <br />
</p>
<button id="back" class="button">Back</button>
</div>
<div class="settings hidden">
<p id="distance">Render Distance: 3</p>
<input
type="range"
id="distance-input"
min="1"
max="8"
value="3"
step="1"
/>
<p id="fov">Field of View: 70</p>
<input
type="range"
id="fov-input"
min="40"
max="100"
value="70"
step="1"
/>
<p id="music">Music: On</p>
<input type="range" id="music-input" min="0" max="1" value="1" step="1" />
<br />
<br />
<button id="setting-back" class="button">Apply</button>
</div>
<div class="save-modal hidden">Game Saved!</div>
<div class="load-modal hidden">Game Loaded!</div>
</body>
</html>
const s: string = "欢迎来到 InsCode";
console.log(s);
{
"name": "minecraft-threejs",
"version": "0.0.0",
"license": "MIT",
"author": "Yulei Zhu",
"description": "Minecraft clone made with Three.js and TypeScript",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview --port 8080",
"lint": "tsc --noEmit"
},
"devDependencies": {
"@types/three": "^0.137.0",
"typescript": "^4.5.5",
"vite": "^2.8.0"
},
"dependencies": {
"guess": "^1.0.2",
"three": "^0.137.0"
}
}
import * as THREE from 'three'
import hal3 from './musics/hal3.ogg'
import { BlockType } from '../terrain'
import grass1 from './blocks/grass1.ogg'
import grass2 from './blocks/grass2.ogg'
import grass3 from './blocks/grass3.ogg'
import grass4 from './blocks/grass4.ogg'
import sand1 from './blocks/sand1.ogg'
import sand2 from './blocks/sand2.ogg'
import sand3 from './blocks/sand3.ogg'
import sand4 from './blocks/sand4.ogg'
import stone1 from './blocks/stone1.ogg'
import stone2 from './blocks/stone2.ogg'
import stone3 from './blocks/stone3.ogg'
import stone4 from './blocks/stone4.ogg'
import dirt1 from './blocks/dirt1.ogg'
import dirt2 from './blocks/dirt2.ogg'
import dirt3 from './blocks/dirt3.ogg'
import dirt4 from './blocks/dirt4.ogg'
import tree1 from './blocks/tree1.ogg'
import tree2 from './blocks/tree2.ogg'
import tree3 from './blocks/tree3.ogg'
import tree4 from './blocks/tree4.ogg'
import leaf1 from './blocks/leaf1.ogg'
import leaf2 from './blocks/leaf2.ogg'
import leaf3 from './blocks/leaf3.ogg'
import leaf4 from './blocks/leaf4.ogg'
import { isMobile } from '../utils'
export default class Audio {
constructor(camera: THREE.PerspectiveCamera) {
if (isMobile) return
const listener = new THREE.AudioListener()
const audioLoader = new THREE.AudioLoader()
camera.add(listener)
// load bgm
const bgm = new THREE.Audio(listener)
bgm.autoplay = false
audioLoader.load(hal3, buffer => {
bgm.setBuffer(buffer)
bgm.setVolume(0.1)
bgm.setLoop(true)
if (bgm.isPlaying) {
bgm.pause()
bgm.play()
}
})
// play / pause bgm
document.addEventListener('pointerlockchange', () => {
if (document.pointerLockElement && !bgm.isPlaying && !this.disabled) {
bgm.play()
} else {
bgm.pause()
}
})
// load sound effect
for (const types of this.sourceSet) {
const audios: THREE.Audio[] = []
for (const type of types) {
audioLoader.load(type, buffer => {
const audio = new THREE.Audio(listener!)
audio.setBuffer(buffer)
audio.setVolume(0.15)
audios.push(audio)
})
}
this.soundSet.push(audios)
}
}
disabled = false
sourceSet = [
[grass1, grass2, grass3, grass4],
[sand1, sand2, sand3, sand4],
[tree1, tree2, tree3, tree4],
[leaf1, leaf2, leaf3, leaf4],
[dirt1, dirt2, dirt3, dirt4],
[stone1, stone2, stone3, stone4],
[stone1, stone2, stone3, stone4],
[tree1, tree2, tree3, tree4],
[stone1, stone2, stone3, stone4],
[stone1, stone2, stone3, stone4],
[stone1, stone2, stone3, stone4]
]
soundSet: THREE.Audio[][] = []
index = 0
playSound(type: BlockType) {
if (!this.disabled && !isMobile) {
this.index++ === 3 && (this.index = 0)
this.soundSet[type]?.[this.index]?.play()
}
}
}
此差异已折叠。
//legacy
import * as THREE from 'three'
import Block from '../../terrain/mesh/block'
import { ImprovedNoise } from 'three/examples/jsm/math/ImprovedNoise'
const noise = new ImprovedNoise()
const raycaster = new THREE.Raycaster(
new THREE.Vector3(),
new THREE.Vector3(0, -1, 0),
0,
1.8
)
onmessage = (
msg: MessageEvent<{
position: THREE.Vector3
far: number
blocks: Block[]
seed: number
noiseGap: number
noiseAmp: number
}>
) => {
raycaster.ray.origin = new THREE.Vector3(
msg.data.position.x,
msg.data.position.y,
msg.data.position.z
)
raycaster.far = msg.data.far
let index = 0
const mesh = new THREE.InstancedMesh(
new THREE.BoxGeometry(1, 1, 1),
new THREE.MeshBasicMaterial(),
100
)
const matrix = new THREE.Matrix4()
let x = Math.round(msg.data.position.x)
let z = Math.round(msg.data.position.z)
let y =
Math.floor(
noise.noise(x / msg.data.noiseGap, z / msg.data.noiseGap, msg.data.seed) *
msg.data.noiseAmp
) + 30
let removed = false
for (const block of msg.data.blocks) {
if (
block.x === Math.round(msg.data.position.x) &&
block.z === Math.round(msg.data.position.z)
) {
if (block.placed) {
matrix.setPosition(new THREE.Vector3(block.x, block.y, block.z))
mesh.setMatrixAt(index++, matrix)
} else if (block.y === y) {
removed = true
}
}
}
if (!removed) {
matrix.setPosition(new THREE.Vector3(x, y, z))
mesh.setMatrixAt(index++, matrix)
}
mesh.instanceMatrix.needsUpdate = true
if (raycaster.intersectObject(mesh).length) {
postMessage(true)
} else {
postMessage(false)
}
}
//legacy
import * as THREE from 'three'
onmessage = (
msg: MessageEvent<{
count: number
matrices: THREE.InstancedBufferAttribute[]
position: THREE.Vector3
}>
) => {
let meshes = []
let raycaster = new THREE.Raycaster(
new THREE.Vector3(
msg.data.position.x,
msg.data.position.y - 1,
msg.data.position.z
),
new THREE.Vector3(1, 0, 0),
0,
0.6
)
for (let matrix of msg.data.matrices) {
let mesh = new THREE.InstancedMesh(
new THREE.BoxGeometry(1, 1, 1),
new THREE.MeshBasicMaterial(),
msg.data.count
)
mesh.instanceMatrix = matrix
meshes.push(mesh)
}
if (raycaster.intersectObjects(meshes).length) {
postMessage(true)
} else {
postMessage(false)
}
}
import * as THREE from 'three'
export default class Core {
constructor() {
this.camera = new THREE.PerspectiveCamera()
this.renderer = new THREE.WebGLRenderer()
this.scene = new THREE.Scene()
this.initScene()
this.initRenderer()
this.initCamera()
}
camera: THREE.PerspectiveCamera
scene: THREE.Scene
renderer: THREE.Renderer
initCamera = () => {
this.camera.fov = 50
this.camera.aspect = window.innerWidth / window.innerHeight
this.camera.near = 0.01
this.camera.far = 500
this.camera.updateProjectionMatrix()
this.camera.position.set(8, 50, 8)
this.camera.lookAt(100, 30, 100)
window.addEventListener('resize', () => {
this.camera.aspect = window.innerWidth / window.innerHeight
this.camera.updateProjectionMatrix()
})
}
initScene = () => {
this.scene = new THREE.Scene()
const backgroundColor = 0x87ceeb
this.scene.fog = new THREE.Fog(backgroundColor, 1, 96)
this.scene.background = new THREE.Color(backgroundColor)
const sunLight = new THREE.PointLight(0xffffff, 0.5)
sunLight.position.set(500, 500, 500)
this.scene.add(sunLight)
const sunLight2 = new THREE.PointLight(0xffffff, 0.2)
sunLight2.position.set(-500, 500, -500)
this.scene.add(sunLight2)
const reflectionLight = new THREE.AmbientLight(0x404040)
this.scene.add(reflectionLight)
}
initRenderer = () => {
this.renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(this.renderer.domElement)
window.addEventListener('resize', () => {
this.renderer.setSize(window.innerWidth, window.innerHeight)
})
}
}
import Core from './core'
import Control from './control'
import Player from './player'
import Terrain from './terrain'
import UI from './ui'
import Audio from './audio'
import './style.css'
const core = new Core()
const camera = core.camera
const scene = core.scene
const renderer = core.renderer
const player = new Player()
const audio = new Audio(camera)
const terrain = new Terrain(scene, camera)
const control = new Control(scene, camera, player, terrain, audio)
const ui = new UI(terrain, control)
// animation
;(function animate() {
// let p1 = performance.now()
requestAnimationFrame(animate)
control.update()
terrain.update()
ui.update()
renderer.render(scene, camera)
// console.log(performance.now()-p1)
})()
export enum Mode {
walking = 'walking',
sprinting = 'sprinting',
flying = 'flying',
sprintFlying = 'sprintFlying',
sneaking = 'sneaking'
}
export enum Speed {
// walking = 4.317,
walking = 5.612,
sprinting = 5.612,
// flying = 10.89,
flying = 21.78,
sprintFlying = 21.78,
sneaking = 1.95
}
export default class Player {
mode = Mode.walking
speed = Speed[this.mode]
setMode(Mode: Mode) {
this.mode = Mode
this.speed = Speed[this.mode]
}
falling = 38.4
jump = 1.2522
body = {
height: 1.8,
width: 0.5
}
}
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="50" height="50" viewBox="0 0 250 250" ><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg>
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册