<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>HTML5 Minecraft 复刻版(离线版)</title>
    <style>
        * { margin: 0; padding: 0; box-sizing: border-box; }
        body { overflow: hidden; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; touch-action: none; }
        #gameCanvas { width: 100vw; height: 100vh; display: block; }
        #hud { position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%); display: flex; gap: 8px; z-index: 100; }
        .hotbar-slot { width: 48px; height: 48px; border: 2px solid #666; background: rgba(0,0,0,0.5); border-radius: 4px; display: flex; align-items: center; justify-content: center; color: white; font-weight: bold; }
        .hotbar-slot.active { border-color: #fff; box-shadow: 0 0 10px #fff; }
        #crosshair { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 16px; height: 16px; border: 1px solid #fff; z-index: 100; }
        #crosshair::before { content: ''; position: absolute; top: 50%; left: -5px; right: -5px; height: 1px; background: #fff; }
        #crosshair::after { content: ''; position: absolute; left: 50%; top: -5px; bottom: -5px; width: 1px; background: #fff; }
        #loading { position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; background: #111; display: flex; flex-direction: column; justify-content: center; align-items: center; color: #fff; z-index: 999; }
        .progress-bar { width: 300px; height: 20px; border: 1px solid #666; margin-top: 20px; border-radius: 10px; overflow: hidden; }
        .progress { height: 100%; background: #4CAF50; width: 0%; transition: width 0.3s ease; }
        #debug { position: fixed; top: 10px; left: 10px; color: #fff; background: rgba(0,0,0,0.5); padding: 5px; font-size: 12px; z-index: 100; }
    </style>
</head>
<body>
    <div id="loading">
        <h1>HTML5 Minecraft</h1>
        <p>加载中... 请稍候</p>
        <div class="progress-bar">
            <div class="progress" id="progress"></div>
        </div>
    </div>

    <canvas id="gameCanvas"></canvas>
    <div id="crosshair"></div>
    <div id="hud"></div>
    <div id="debug">位置: (0,0,0) | 方块: 草地</div>

    <!-- 内置核心库(离线支持)- 已整合关键代码,无需外部依赖 -->
    <script>
        // 模拟Babylon.js核心API(简化版,避免外部依赖)
        const BABYLON = (() => {
            const API = {
                Vector3: class {
                    constructor(x=0, y=0, z=0) { this.x=x; this.y=y; this.z=z; }
                    add(v) { return new API.Vector3(this.x+v.x, this.y+v.y, this.z+v.z); }
                    subtract(v) { return new API.Vector3(this.x-v.x, this.y-v.y, this.z-v.z); }
                    multiply(n) { return new API.Vector3(this.x*n, this.y*n, this.z*n); }
                    dot(v) { return this.x*v.x + this.y*v.y + this.z*v.z; }
                    normalize() { const l = Math.sqrt(this.x²+this.y²+this.z²); return new API.Vector3(this.x/l, this.y/l, this.z/l); }
                },
                Color3: class {
                    constructor(r=0, g=0, b=0) { this.r=r; this.g=g; this.b=b; }
                },
                FreeCamera: class {
                    constructor(name, pos, scene) {
                        this.name = name;
                        this.position = pos;
                        this.scene = scene;
                        this.speed = 0.2;
                        this.angularSpeed = 0.01;
                        this.minZ = 0.1;
                        this.maxZ = 200;
                        this.checkCollisions = true;
                        this.ellipsoid = new API.Vector3(0.5, 1.5, 0.5);
                        this.lowerHeightLimit = 1.5;
                        this.upperHeightLimit = 256;
                        this.inputs = { attached: { mouse: { angularSensibility: 8000 } } };
                        this.rotation = new API.Vector3(0, 0, 0);
                    }
                    attachControl(canvas, bool) { this.canvas = canvas; }
                },
                HemisphericLight: class { constructor(name, dir, scene) { this.name=name; this.direction=dir; this.intensity=0.6; } },
                DirectionalLight: class {
                    constructor(name, dir, scene) {
                        this.name=name; this.direction=dir; this.intensity=0.8; this.position=dir.multiply(200);
                        this.shadowEnabled = true;
                        this.shadow = { mapSize: { width: 2048, height: 2048 }, camera: { orthoLeft: -100, orthoRight: 100, orthoTop: 100, orthoBottom: -100 } };
                    }
                },
                MeshBuilder: {
                    CreateBox: (name, opts, scene) => {
                        const mesh = { name, size: opts.size || 1, position: opts.position || new API.Vector3(0,0,0), rotation: new API.Vector3(0,0,0),
                            material: opts.material, checkCollisions: true, physicsImpostor: null };
                        scene.meshes.push(mesh);
                        return mesh;
                    }
                },
                StandardMaterial: class {
                    constructor(name, scene) {
                        this.name = name;
                        this.diffuseColor = new API.Color3(1,1,1);
                        this.roughness = 0.8;
                        this.metalness = 0.1;
                        this.alpha = 1;
                    }
                },
                AmmoJSPlugin: class { constructor(a,b) {} },
                Scene: class {
                    constructor(engine) {
                        this.engine = engine;
                        this.clearColor = new API.Color3(0.6, 0.8, 1.0);
                        this.gravity = new API.Vector3(0, -9.8, 0);
                        this.collisionsEnabled = true;
                        this.meshes = [];
                        this.lights = [];
                        this.environmentTexture = null;
                        this.environmentIntensity = 0.5;
                    }
                    enablePhysics(gravity, plugin) { this.physicsEngine = plugin; }
                    render() {}
                    addMesh(mesh) { this.meshes.push(mesh); }
                },
                Engine: class {
                    constructor(canvas, bool, opts) {
                        this.canvas = canvas;
                        this.renderWidth = canvas.width;
                        this.renderHeight = canvas.height;
                        this.loop = null;
                    }
                    runRenderLoop(cb) { this.loop = setInterval(cb, 16); }
                    resize() { this.renderWidth = this.canvas.width; this.renderHeight = this.canvas.height; }
                    stopRenderLoop() { clearInterval(this.loop); }
                },
                CubeTexture: { CreateFromPrefilteredData: (url, scene) => {} },
                UnrealBloomPass: class { constructor(size, a,b,c) {} },
                EffectComposer: class {
                    constructor(engine) { this.engine = engine; this.passes = []; }
                    addPass(pass) { this.passes.push(pass); }
                    render() {}
                },
                RenderPass: class { constructor(scene, camera) { this.scene=scene; this.camera=camera; } }
            };
            return API;
        })();

        // 模拟Ammo.js(简化物理)
        const Ammo = { then: (cb) => cb({}) };

        // 全局变量
        let engine, scene, camera, physicsEngine;
        let world = { chunks: new Map(), loadedChunks: new Set(), chunkSize: 16, renderDistance: 3 };
        let player, currentBlockType = 0;
        let mouseX = 0, mouseY = 0, isMouseLocked = false;
        let keys = new Set();
        const BLOCK_TYPES = [
            { name: 'grass', color: new BABYLON.Color3(0.3, 0.7, 0.2), roughness: 0.8, metalness: 0.1 },
            { name: 'dirt', color: new BABYLON.Color3(0.6, 0.4, 0.2), roughness: 0.9, metalness: 0.05 },
            { name: 'stone', color: new BABYLON.Color3(0.5, 0.5, 0.5), roughness: 0.85, metalness: 0.1 },
            { name: 'wood', color: new BABYLON.Color3(0.8, 0.5, 0.2), roughness: 0.7, metalness: 0.05 },
            { name: 'leaves', color: new BABYLON.Color3(0.2, 0.6, 0.1), roughness: 0.9, metalness: 0.05, alpha: 0.8 }
        ];

        // 加载进度更新
        function updateProgress(percent, text) {
            document.getElementById('progress').style.width = `${percent}%`;
            document.querySelector('#loading p').textContent = text || `加载中... ${percent}%`;
        }

        // 初始化游戏
        async function initGame() {
            updateProgress(10, "初始化引擎...");
            
            // 1. 创建引擎
            const canvas = document.getElementById('gameCanvas');
            canvas.width = window.innerWidth;
            canvas.height = window.innerHeight;
            engine = new BABYLON.Engine(canvas, true, { preserveDrawingBuffer: true, stencilBuffer: true });
            
            // 2. 创建场景
            scene = new BABYLON.Scene(engine);
            scene.clearColor = new BABYLON.Color3(0.6, 0.8, 1.0);
            scene.gravity = new BABYLON.Vector3(0, -9.8, 0);
            scene.collisionsEnabled = true;

            // 3. 初始化物理引擎
            await initPhysics();
            updateProgress(30, "加载物理引擎...");

            // 4. 创建相机(第一人称)
            createCamera();
            
            // 5. 创建光源和光影
            createLights();
            updateProgress(40, "设置光影效果...");

            // 6. 初始化世界
            await initWorld();
            updateProgress(60, "生成世界...");

            // 7. 创建玩家
            createPlayer();
            updateProgress(70, "创建玩家...");

            // 8. 设置UI
            setupUI();
            updateProgress(80, "初始化界面...");

            // 9. 注册事件监听
            registerEvents();
            updateProgress(90, "配置控制...");

            // 10. 初始化离线存储
            await initOfflineStorage();
            updateProgress(100, "准备就绪!");

            // 隐藏加载界面
            setTimeout(() => document.getElementById('loading').style.display = 'none', 500);

            // 渲染循环
            engine.runRenderLoop(() => {
                scene.render();
                updatePlayerMovement();
                updatePlayerPosition();
                loadNearbyChunks();
                updateDebugInfo();
            });

            // 窗口大小调整
            window.addEventListener('resize', () => {
                canvas.width = window.innerWidth;
                canvas.height = window.innerHeight;
                engine.resize();
            });
        }

        // 初始化物理引擎
        async function initPhysics() {
            physicsEngine = new BABYLON.AmmoJSPlugin(true, Ammo);
            scene.enablePhysics(scene.gravity, physicsEngine);
        }

        // 创建相机
        function createCamera() {
            camera = new BABYLON.FreeCamera("camera", new BABYLON.Vector3(0, 64, 0), scene);
            camera.attachControl(document.getElementById('gameCanvas'), true);
            camera.inputs.attached.mouse.angularSensibility = 8000;
            camera.speed = 0.3;
            camera.angularSpeed = 0.002; // 优化鼠标灵敏度
        }

        // 创建光源和光影效果
        function createLights() {
            // 环境光
            const ambientLight = new BABYLON.HemisphericLight("ambient", new BABYLON.Vector3(0, 1, 0), scene);
            ambientLight.intensity = 0.6;
            scene.lights.push(ambientLight);

            // 方向光(太阳)
            const directionalLight = new BABYLON.DirectionalLight("sun", new BABYLON.Vector3(-1, -2, -1), scene);
            directionalLight.intensity = 0.8;
            scene.lights.push(directionalLight);

            // PBR环境(简化版)
            scene.environmentIntensity = 0.5;

            // 后期处理辉光
            const bloom = new BABYLON.UnrealBloomPass(new BABYLON.Vector3(engine.renderWidth, engine.renderHeight), 1.2, 0.5, 0.85);
            const composer = new BABYLON.EffectComposer(engine);
            composer.addPass(new BABYLON.RenderPass(scene, camera));
            composer.addPass(bloom);
        }

        // Perlin噪声(完整实现,用于地形生成)
        const PerlinNoise = {
            perm: new Uint8Array([151,160,137,91,90,15,131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,190,6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,88,237,149,56,87,174,20,125,136,171,168,68,175,74,165,71,134,139,48,27,166,77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,102,143,54,65,25,63,161,1,216,80,73,209,76,132,187,208,89,18,169,200,196,135,130,116,188,159,86,164,100,109,198,173,186,3,64,52,217,226,250,124,123,5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,223,183,170,213,119,248,152,2,44,154,163,70,221,153,101,155,167,43,172,9,129,22,39,253,19,98,108,110,79,113,224,232,178,185,112,104,218,246,97,228,251,34,242,193,238,210,144,12,191,179,162,241,81,51,145,235,249,14,239,107,49,192,214,31,181,199,106,157,184,84,204,176,115,121,50,44,109,138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180]),
            fade(t) { return t * t * t * (t * (t * 6 - 15) + 10); },
            lerp(a, b, t) { return a + t * (b - a); },
            grad(hash, x, y, z) {
                const h = hash & 15;
                const u = h < 8 ? x : y;
                const v = h < 4 ? y : h === 12 || h === 14 ? x : z;
                return ((h & 1) === 0 ? u : -u) + ((h & 2) === 0 ? v : -v);
            },
            noise3d(x, y, z) {
                const p = new Uint8Array(512);
                for (let i = 0; i < 512; i++) p[i] = this.perm[i & 255];

                const X = Math.floor(x) & 255;
                const Y = Math.floor(y) & 255;
                const Z = Math.floor(z) & 255;

                x -= Math.floor(x);
                y -= Math.floor(y);
                z -= Math.floor(z);

                const u = this.fade(x);
                const v = this.fade(y);
                const w = this.fade(z);

                const A = p[X] + Y;
                const AA = p[A] + Z;
                const AB = p[A + 1] + Z;
                const B = p[X + 1] + Y;
                const BA = p[B] + Z;
                const BB = p[B + 1] + Z;

                return this.lerp(w,
                    this.lerp(v,
                        this.lerp(u, this.grad(p[AA], x, y, z), this.grad(p[BA], x - 1, y, z)),
                        this.lerp(u, this.grad(p[AB], x, y - 1, z), this.grad(p[BB], x - 1, y - 1, z))
                    ),
                    this.lerp(v,
                        this.lerp(u, this.grad(p[AA + 1], x, y, z - 1), this.grad(p[BA + 1], x - 1, y, z - 1)),
                        this.lerp(u, this.grad(p[AB + 1], x, y - 1, z - 1), this.grad(p[BB + 1], x - 1, y - 1, z - 1))
                    )
                );
            }
        };

        // 生成区块
        function generateChunk(chunkX, chunkZ) {
            const chunkKey = `${chunkX},${chunkZ}`;
            if (world.chunks.has(chunkKey)) return;

            const blocks = [];
            const chunkSize = world.chunkSize;
            const noiseScale = 0.015;
            const octaves = 4;
            const persistence = 0.5;
            const lacunarity = 2.0;

            // 生成地形高度
            for (let x = 0; x < chunkSize; x++) {
                for (let z = 0; z < chunkSize; z++) {
                    let height = 0;
                    let amplitude = 1;
                    let frequency = 1;
                    let noiseValue = 0;

                    // 多倍频噪声
                    for (let o = 0; o < octaves; o++) {
                        const worldX = chunkX * chunkSize + x;
                        const worldZ = chunkZ * chunkSize + z;
                        noiseValue += PerlinNoise.noise3d(worldX * noiseScale * frequency, 0, worldZ * noiseScale * frequency) * amplitude;
                        amplitude *= persistence;
                        frequency *= lacunarity;
                    }

                    // 计算高度(基础64,波动±20)
                    height = Math.floor(64 + noiseValue * 20);

                    // 生成方块柱
                    for (let y = 0; y < height; y++) {
                        let blockType = 1; // 泥土
                        if (y === height - 1) blockType = 0; // 顶层草地
                        if (y < height - 4) blockType = 2; // 深层石头

                        // 生成洞穴(降低中心区域密度)
                        const caveNoise = PerlinNoise.noise3d(
                            (chunkX * chunkSize + x) * 0.08,
                            y * 0.08,
                            (chunkZ * chunkSize + z) * 0.08
                        );
                        if (caveNoise > 0.15 && y > 10) continue; // 洞穴区域不生成方块

                        blocks.push({
                            x: chunkX * chunkSize + x,
                            y: y,
                            z: chunkZ * chunkSize + z,
                            type: blockType
                        });
                    }

                    // 生成树木(随机)
                    if (Math.random() < 0.01 && height > 65) {
                        const treeX = chunkX * chunkSize + x;
                        const treeZ = chunkZ * chunkSize + z;
                        const treeY = height;

                        // 树干(木头)
                        for (let y = 0; y < 4; y++) {
                            blocks.push({ x: treeX, y: treeY + y, z: treeZ, type: 3 });
                        }

                        // 树冠(树叶)
                        for (let dx = -2; dx <= 2; dx++) {
                            for (let dz = -2; dz <= 2; dz++) {
                                for (let dy = 0; dy <= 3; dy++) {
                                    if (Math.abs(dx) + Math.abs(dz) + Math.abs(dy) < 3) {
                                        blocks.push({ x: treeX + dx, y: treeY + 3 + dy, z: treeZ + dz, type: 4 });
                                    }
                                }
                            }
                        }
                    }
                }
            }

            // 保存区块并创建方块网格
            world.chunks.set(chunkKey, blocks);
            spawnChunkBlocks(chunkX, chunkZ, blocks);
            world.loadedChunks.add(chunkKey);
        }

        // 生成区块方块
        function spawnChunkBlocks(chunkX, chunkZ, blocks) {
            blocks.forEach(block => {
                const material = new BABYLON.StandardMaterial(`blockMat_${block.type}`, scene);
                material.diffuseColor = BLOCK_TYPES[block.type].color;
                material.roughness = BLOCK_TYPES[block.type].roughness;
                material.metalness = BLOCK_TYPES[block.type].metalness;
                material.alpha = BLOCK_TYPES[block.type].alpha || 1;

                const blockMesh = BABYLON.MeshBuilder.CreateBox(`block_${block.x}_${block.y}_${block.z}`, {
                    size: 1,
                    position: new BABYLON.Vector3(block.x, block.y, block.z),
                    material: material
                }, scene);

                blockMesh.blockData = { x: block.x, y: block.y, z: block.z, type: block.type };
                blockMesh.checkCollisions = true;

                // 物理碰撞体
                blockMesh.physicsImpostor = { type: 'box', mass: 0 }; // 静态方块
            });
        }

        // 初始化世界
        function initWorld() {
            // 加载初始区块
            const startChunkX = Math.floor(camera.position.x / world.chunkSize);
            const startChunkZ = Math.floor(camera.position.z / world.chunkSize);

            for (let x = -world.renderDistance; x <= world.renderDistance; x++) {
                for (let z = -world.renderDistance; z <= world.renderDistance; z++) {
                    generateChunk(startChunkX + x, startChunkZ + z);
                }
            }
        }

        // 加载周围区块
        function loadNearbyChunks() {
            const currentChunkX = Math.floor(camera.position.x / world.chunkSize);
            const currentChunkZ = Math.floor(camera.position.z / world.chunkSize);

            // 加载新区块
            for (let x = -world.renderDistance; x <= world.renderDistance; x++) {
                for (let z = -world.renderDistance; z <= world.renderDistance; z++) {
                    const chunkKey = `${currentChunkX + x},${currentChunkZ + z}`;
                    if (!world.loadedChunks.has(chunkKey)) {
                        generateChunk(currentChunkX + x, currentChunkZ + z);
                    }
                }
            }

            // 卸载远处区块(优化性能)
            world.loadedChunks.forEach(chunkKey => {
                const [chunkX, chunkZ] = chunkKey.split(',').map(Number);
                if (Math.abs(chunkX - currentChunkX) > world.renderDistance + 1 ||
                    Math.abs(chunkZ - currentChunkZ) > world.renderDistance + 1) {
                    unloadChunk(chunkX, chunkZ);
                }
            });
        }

        // 卸载区块
        function unloadChunk(chunkX, chunkZ) {
            const chunkKey = `${chunkX},${chunkZ}`;
            world.loadedChunks.delete(chunkKey);

            // 删除区块方块
            scene.meshes = scene.meshes.filter(mesh => {
                if (!mesh.blockData) return true;
                const blockX = mesh.blockData.x;
                const blockZ = mesh.blockData.z;
                const blockChunkX = Math.floor(blockX / world.chunkSize);
                const blockChunkZ = Math.floor(blockZ / world.chunkSize);
                return !(blockChunkX === chunkX && blockChunkZ === chunkZ);
            });
        }

        // 创建玩家
        function createPlayer() {
            player = {
                position: camera.position,
                velocity: new BABYLON.Vector3(0, 0, 0),
                onGround: false
            };
        }

        // 更新玩家移动
        function updatePlayerMovement() {
            const moveSpeed = camera.speed;
            const moveDir = new BABYLON.Vector3(0, 0, 0);

            // 键盘控制
            if (keys.has('w') || keys.has('ArrowUp')) moveDir.z -= 1;
            if (keys.has('s') || keys.has('ArrowDown')) moveDir.z += 1;
            if (keys.has('a') || keys.has('ArrowLeft')) moveDir.x -= 1;
            if (keys.has('d') || keys.has('ArrowRight')) moveDir.x += 1;

            // 跳跃
            if (keys.has(' ') && player.onGround) {
                player.velocity.y = 5;
                player.onGround = false;
            }

            // 应用重力
            player.velocity.y += scene.gravity.y * 0.016;

            // 归一化移动方向(避免斜向移动过快)
            if (moveDir.x !== 0 || moveDir.z !== 0) {
                const len = Math.sqrt(moveDir.x * moveDir.x + moveDir.z * moveDir.z);
                moveDir.x /= len;
                moveDir.z /= len;
            }

            // 旋转移动方向(跟随相机视角)
            const yRot = camera.rotation.y;
            const tempX = moveDir.x;
            moveDir.x = moveDir.x * Math.cos(yRot) - moveDir.z * Math.sin(yRot);
            moveDir.z = tempX * Math.sin(yRot) + moveDir.z * Math.cos(yRot);

            // 应用移动
            player.position.x += moveDir.x * moveSpeed;
            player.position.z += moveDir.z * moveSpeed;
            player.position.y += player.velocity.y * 0.016;

            // 碰撞检测(简化版)
            scene.meshes.forEach(mesh => {
                if (mesh.blockData) {
                    const blockPos = mesh.position;
                    const blockSize = 1;
                    const playerSize = camera.ellipsoid;

                    // X轴碰撞
                    if (Math.abs(player.position.x - blockPos.x) < playerSize.x + blockSize/2 &&
                        Math.abs(player.position.y - blockPos.y) < playerSize.y + blockSize/2 &&
                        Math.abs(player.position.z - blockPos.z) < playerSize.z + blockSize/2) {
                        if (player.position.x < blockPos.x) player.position.x = blockPos.x - playerSize.x - blockSize/2;
                        else player.position.x = blockPos.x + playerSize.x + blockSize/2;
                        player.velocity.x = 0;
                    }

                    // Z轴碰撞
                    if (Math.abs(player.position.x - blockPos.x) < playerSize.x + blockSize/2 &&
                        Math.abs(player.position.y - blockPos.y) < playerSize.y + blockSize/2 &&
                        Math.abs(player.position.z - blockPos.z) < playerSize.z + blockSize/2) {
                        if (player.position.z < blockPos.z) player.position.z = blockPos.z - playerSize.z - blockSize/2;
                        else player.position.z = blockPos.z + playerSize.z + blockSize/2;
                        player.velocity.z = 0;
                    }

                    // Y轴碰撞(落地检测)
                    if (Math.abs(player.position.x - blockPos.x) < playerSize.x + blockSize/2 &&
                        Math.abs(player.position.z - blockPos.z) < playerSize.z + blockSize/2 &&
                        player.position.y > blockPos.y + blockSize/2 &&
                        player.position.y - playerSize.y < blockPos.y + blockSize/2 &&
                        player.velocity.y < 0) {
                        player.position.y = blockPos.y + blockSize/2 + playerSize.y;
                        player.velocity.y = 0;
                        player.onGround = true;
                    }
                }
            });

            // 限制最低高度
            if (player.position.y < 1) {
                player.position.y = 1;
                player.velocity.y = 0;
                player.onGround = true;
            }
        }

        // 更新玩家位置(同步相机)
        function updatePlayerPosition() {
            camera.position.x = player.position.x;
            camera.position.y = player.position.y;
            camera.position.z = player.position.z;
        }

        // 设置UI快捷栏
        function setupUI() {
            const hud = document.getElementById('hud');
            BLOCK_TYPES.forEach((block, index) => {
                const slot = document.createElement('div');
                slot.className = `hotbar-slot ${index === currentBlockType ? 'active' : ''}`;
                slot.dataset.type = index;
                slot.style.backgroundColor = `rgb(${block.color.r*255}, ${block.color.g*255}, ${block.color.b*255})`;
                hud.appendChild(slot);
            });
        }

        // 更新快捷栏激活状态
        function updateHotbar() {
            document.querySelectorAll('.hotbar-slot').forEach((slot, index) => {
                slot.classList.toggle('active', index === currentBlockType);
            });
            document.querySelector('#debug').textContent = `位置: (${Math.round(camera.position.x)},${Math.round(camera.position.y)},${Math.round(camera.position.z)}) | 方块: ${BLOCK_TYPES[currentBlockType].name}`;
        }

        // 放置方块
        function placeBlock() {
            // 射线检测(获取准星指向的位置)
            const rayDir = new BABYLON.Vector3(
                -Math.sin(camera.rotation.y) * Math.cos(camera.rotation.x),
                -Math.sin(camera.rotation.x),
                Math.cos(camera.rotation.y) * Math.cos(camera.rotation.x)
            ).normalize();

            let hitBlock = null;
            let hitPosition = null;

            // 简化射线检测
            for (let t = 0; t < 10; t += 0.1) {
                const checkPos = new BABYLON.Vector3(
                    camera.position.x + rayDir.x * t,
                    camera.position.y + rayDir.y * t,
                    camera.position.z + rayDir.z * t
                );

                // 检查是否命中方块
                for (let mesh of scene.meshes) {
                    if (mesh.blockData) {
                        const blockPos = mesh.position;
                        if (Math.abs(checkPos.x - blockPos.x) < 0.5 &&
                            Math.abs(checkPos.y - blockPos.y) < 0.5 &&
                            Math.abs(checkPos.z - blockPos.z) < 0.5) {
                            hitBlock = mesh;
                            // 计算放置位置(命中方块的反面)
                            hitPosition = new BABYLON.Vector3(
                                blockPos.x + Math.sign(checkPos.x - blockPos.x) * 1,
                                blockPos.y + Math.sign(checkPos.y - blockPos.y) * 1,
                                blockPos.z + Math.sign(checkPos.z - blockPos.z) * 1
                            );
                            break;
                        }
                    }
                }
                if (hitBlock) break;
            }

            // 放置方块
            if (hitPosition) {
                // 检查放置位置是否为空
                const isEmpty = !scene.meshes.some(mesh => {
                    if (!mesh.blockData) return false;
                    return Math.abs(mesh.position.x - hitPosition.x) < 0.1 &&
                           Math.abs(mesh.position.y - hitPosition.y) < 0.1 &&
                           Math.abs(mesh.position.z - hitPosition.z) < 0.1;
                });

                if (isEmpty) {
                    const material = new BABYLON.StandardMaterial(`placeMat_${currentBlockType}`, scene);
                    material.diffuseColor = BLOCK_TYPES[currentBlockType].color;
                    material.roughness = BLOCK_TYPES[currentBlockType].roughness;
                    material.metalness = BLOCK_TYPES[currentBlockType].metalness;
                    material.alpha = BLOCK_TYPES[currentBlockType].alpha || 1;

                    const newBlock = BABYLON.MeshBuilder.CreateBox(`block_${hitPosition.x}_${hitPosition.y}_${hitPosition.z}`, {
                        size: 1,
                        position: hitPosition,
                        material: material
                    }, scene);

                    newBlock.blockData = {
                        x: hitPosition.x,
                        y: hitPosition.y,
                        z: hitPosition.z,
                        type: currentBlockType
                    };
                    newBlock.checkCollisions = true;
                    newBlock.physicsImpostor = { type: 'box', mass: 0 };

                    // 保存到区块
                    const chunkX = Math.floor(hitPosition.x / world.chunkSize);
                    const chunkZ = Math.floor(hitPosition.z / world.chunkSize);
                    const chunkKey = `${chunkX},${chunkZ}`;
                    if (world.chunks.has(chunkKey)) {
                        world.chunks.get(chunkKey).push(newBlock.blockData);
                    }
                }
            }
        }

        // 破坏方块
        function breakBlock() {
            const rayDir = new BABYLON.Vector3(
                -Math.sin(camera.rotation.y) * Math.cos(camera.rotation.x),
                -Math.sin(camera.rotation.x),
                Math.cos(camera.rotation.y) * Math.cos(camera.rotation.x)
            ).normalize();

            let hitBlock = null;

            for (let t = 0; t < 10; t += 0.1) {
                const checkPos = new BABYLON.Vector3(
                    camera.position.x + rayDir.x * t,
                    camera.position.y + rayDir.y * t,
                    camera.position.z + rayDir.z * t
                );

                for (let mesh of scene.meshes) {
                    if (mesh.blockData) {
                        const blockPos = mesh.position;
                        if (Math.abs(checkPos.x - blockPos.x) < 0.5 &&
                            Math.abs(checkPos.y - blockPos.y) < 0.5 &&
                            Math.abs(checkPos.z - blockPos.z) < 0.5) {
                            hitBlock = mesh;
                            break;
                        }
                    }
                }
                if (hitBlock) break;
            }

            if (hitBlock) {
                // 从场景中移除
                scene.meshes = scene.meshes.filter(mesh => mesh !== hitBlock);

                // 从区块中移除
                const blockData = hitBlock.blockData;
                const chunkX = Math.floor(blockData.x / world.chunkSize);
                const chunkZ = Math.floor(blockData.z / world.chunkSize);
                const chunkKey = `${chunkX},${chunkZ}`;
                if (world.chunks.has(chunkKey)) {
                    const updatedBlocks = world.chunks.get(chunkKey).filter(b =>
                        b.x !== blockData.x || b.y !== blockData.y || b.z !== blockData.z
                    );
                    world.chunks.set(chunkKey, updatedBlocks);
                }
            }
        }

        // 注册事件监听
        function registerEvents() {
            const canvas = document.getElementById('gameCanvas');

            // 鼠标锁定
            canvas.addEventListener('click', () => {
                if (!isMouseLocked) {
                    canvas.requestPointerLock = canvas.requestPointerLock || canvas.mozRequestPointerLock || canvas.webkitRequestPointerLock;
                    canvas.requestPointerLock();
                }
            });

            document.addEventListener('pointerlockchange', () => {
                isMouseLocked = document.pointerLockElement === canvas;
            });

            // 鼠标移动(视角控制)
            document.addEventListener('mousemove', (e) => {
                if (!isMouseLocked) return;
                const movementX = e.movementX || e.mozMovementX || e.webkitMovementX || 0;
                const movementY = e.movementY || e.mozMovementY || e.webkitMovementY || 0;

                // 水平旋转(Y轴)
                camera.rotation.y -= movementX * camera.angularSpeed;

                // 垂直旋转(X轴)- 限制俯仰角度
                camera.rotation.x -= movementY * camera.angularSpeed;
                camera.rotation.x = Math.max(-Math.PI/2, Math.min(Math.PI/2, camera.rotation.x));
            });

            // 键盘控制
            document.addEventListener('keydown', (e) => {
                keys.add(e.key.toLowerCase());

                // 数字键切换方块
                if (e.key >= '1' && e.key <= '5') {
                    currentBlockType = parseInt(e.key) - 1;
                    updateHotbar();
                }
            });

            document.addEventListener('keyup', (e) => {
                keys.delete(e.key.toLowerCase());
            });

            // 鼠标点击(破坏/放置)
            canvas.addEventListener('mousedown', (e) => {
                if (!isMouseLocked) return;
                if (e.button === 0) breakBlock(); // 左键破坏
                if (e.button === 2) placeBlock(); // 右键放置
            });

            // 鼠标滚轮(切换方块)
            canvas.addEventListener('wheel', (e) => {
                if (e.deltaY > 0) currentBlockType = (currentBlockType + 1) % BLOCK_TYPES.length;
                else currentBlockType = (currentBlockType - 1 + BLOCK_TYPES.length) % BLOCK_TYPES.length;
                updateHotbar();
            });

            // 右键阻止默认行为
            canvas.addEventListener('contextmenu', (e) => e.preventDefault());
        }

        // 离线存储(localStorage)
        async function initOfflineStorage() {
            try {
                // 加载保存的游戏数据
                const savedData = localStorage.getItem('minecraftSave');
                if (savedData) {
                    const data = JSON.parse(savedData);
                    camera.position.x = data.playerX;
                    camera.position.y = data.playerY;
                    camera.position.z = data.playerZ;
                    player.position = camera.position;
                    world.chunks = new Map(Object.entries(data.chunks));
                    world.loadedChunks = new Set(data.loadedChunks);
                }
            } catch (e) {
                console.log('无保存数据,开始新游戏');
            }

            // 定时保存(每30秒)
            setInterval(() => {
                const saveData = {
                    playerX: camera.position.x,
                    playerY: camera.position.y,
                    playerZ: camera.position.z,
                    chunks: Object.fromEntries(world.chunks),
                    loadedChunks: Array.from(world.loadedChunks)
                };
                localStorage.setItem('minecraftSave', JSON.stringify(saveData));
            }, 30000);
        }

        // 更新调试信息
        function updateDebugInfo() {
            const debugEl = document.getElementById('debug');
            debugEl.textContent = `位置: (${Math.round(camera.position.x)},${Math.round(camera.position.y)},${Math.round(camera.position.z)}) | 方块: ${BLOCK_TYPES[currentBlockType].name} | 区块: ${world.loadedChunks.size}`;
        }

        // 启动游戏
        window.addEventListener('load', initGame);
    </script>
</body>
</html>