modify this code by adding rendering trees<!DOCTYPE html>
<html>
<head>
    <title>Infinite Minecraft Clone</title>
    <style>
        body {
            margin: 0;
            overflow: hidden;
        }
        canvas {
            width: 100vw;
            height: 100vh;
            display: block;
        }
        #instructions {
            position: fixed;
            top: 10px;
            left: 10px;
            color: white;
            font-family: Arial, sans-serif;
            background: rgba(0,0,0,0.5);
            padding: 10px;
            border-radius: 5px;
            max-width: 200px;
        }
        #debug {
            position: fixed;
            top: 10px;
            right: 10px;
            color: white;
            font-family: Arial, sans-serif;
            background: rgba(0,0,0,0.5);
            padding: 10px;
            border-radius: 5px;
            max-width: 300px;
            white-space: pre-wrap;
        }
    </style>
</head>
<body>
    <div id="instructions">
        <strong>Controls:</strong><br>
        W/A/S/D - Move<br>
        SPACE - Jump<br>
        LEFT CLICK - Remove block<br>
        RIGHT CLICK - Place block<br>
        MOUSE - Look around
    </div>
    <div id="debug"></div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
    <script>
        // Initialize Three.js
        const scene = new THREE.Scene();
        scene.background = new THREE.Color(0x87CEEB);

        const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
        const renderer = new THREE.WebGLRenderer({ antialias: true });
        renderer.setSize(window.innerWidth, window.innerHeight);
        document.body.appendChild(renderer.domElement);

        // Lighting
        const ambientLight = new THREE.AmbientLight(0xffffff, 0.6);
        scene.add(ambientLight);

        const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
        directionalLight.position.set(10, 20, 10);
        scene.add(directionalLight);

        // Chunk management
        const CHUNK_SIZE = 16;
        const RENDER_DISTANCE = 4;
        const loadedChunks = new Map();

        // Simplified noise function for terrain generation
        function noise(x, z) {
            return Math.floor(Math.sin(x * 0.1) * Math.cos(z * 0.1) * 5 + 
                   Math.sin(x * 0.3 + z * 0.2) * 2);
        }

        // Block creation
        const blockGeometry = new THREE.BoxGeometry(1, 1, 1);
        const blockMaterial = new THREE.MeshLambertMaterial({
            color: 0x2E8B57
        });

        // Function to check if a block exists at given coordinates
        function hasBlockAt(x, y, z) {
            const chunkX = Math.floor(x / CHUNK_SIZE);
            const chunkZ = Math.floor(z / CHUNK_SIZE);
            const chunkKey = `${chunkX},${chunkZ}`;
            const chunk = loadedChunks.get(chunkKey);
            if (!chunk) return false;
            for (let block of chunk.children) {
                if (block.position.x === x && block.position.y === y && block.position.z === z) {
                    return true;
                }
            }
            return false;
        }

        // Generate a single chunk
        function generateChunk(chunkX, chunkZ) {
            const chunk = new THREE.Group();
            chunk.name = `chunk_${chunkX}_${chunkZ}`;

            for (let x = 0; x < CHUNK_SIZE; x++) {
                for (let z = 0; z < CHUNK_SIZE; z++) {
                    const worldX = chunkX * CHUNK_SIZE + x;
                    const worldZ = chunkZ * CHUNK_SIZE + z;
                    
                    // Generate height using noise
                    const height = noise(worldX, worldZ) + 1; // Ensure at least y=1

                    // Create blocks from bottom to height
                    for (let y = -5; y <= height; y++) {
                        const block = new THREE.Mesh(blockGeometry, blockMaterial);
                        block.position.set(worldX, y, worldZ);
                        chunk.add(block);
                    }
                }
            }
            
            return chunk;
        }

        // Load chunks around position
        function loadChunksAroundPosition(position) {
            const centerChunkX = Math.floor(position.x / CHUNK_SIZE);
            const centerChunkZ = Math.floor(position.z / CHUNK_SIZE);

            // Track which chunks should be kept
            const chunksToKeep = new Set();

            // Load new chunks
            for (let dx = -RENDER_DISTANCE; dx <= RENDER_DISTANCE; dx++) {
                for (let dz = -RENDER_DISTANCE; dz <= RENDER_DISTANCE; dz++) {
                    const chunkX = centerChunkX + dx;
                    const chunkZ = centerChunkZ + dz;
                    const chunkKey = `${chunkX},${chunkZ}`;
                    chunksToKeep.add(chunkKey);

                    if (!loadedChunks.has(chunkKey)) {
                        const chunk = generateChunk(chunkX, chunkZ);
                        loadedChunks.set(chunkKey, chunk);
                        scene.add(chunk);
                    }
                }
            }

            // Unload distant chunks
            for (const [key, chunk] of loadedChunks) {
                if (!chunksToKeep.has(key)) {
                    scene.remove(chunk);
                    loadedChunks.delete(key);
                }
            }

            // Update debug info
            document.getElementById('debug').textContent = 
                `Loaded chunks: ${loadedChunks.size}\n` +
                `Player Position: (${Math.round(position.x)}, ${Math.round(position.y)}, ${Math.round(position.z)})`;
        }

        // Player movement variables
        const player = {
            position: new THREE.Vector3(0, 6, 0), // Start slightly above ground
            velocity: new THREE.Vector3(),
            onGround: false,
            speed: 0.2,
            jumpForce: 0.3
        };

        // Camera controls
        let pitch = 0;
        let yaw = 0;

        // Movement controls
        const keys = {};

        // Raycaster for block placement/removal
        const raycaster = new THREE.Raycaster();
        const mouse = new THREE.Vector2();

        // Block placement helper function
        function placeBlock(intersectPoint, normal) {
            const position = new THREE.Vector3()
                .copy(intersectPoint)
                .add(normal)
                .floor(); // Ensure integer positions

            // Check if there's a block below the intended position
            if (!hasBlockAt(position.x, position.y - 1, position.z)) {
                console.log("Cannot place block in the air. A block below is required.");
                return;
            }

            // Prevent duplicate blocks
            if (hasBlockAt(position.x, position.y, position.z)) {
                console.log("Block already exists at this position.");
                return;
            }

            const chunkX = Math.floor(position.x / CHUNK_SIZE);
            const chunkZ = Math.floor(position.z / CHUNK_SIZE);
            const chunkKey = `${chunkX},${chunkZ}`;
            let chunk = loadedChunks.get(chunkKey);

            if (!chunk) {
                // If the chunk isn't loaded yet, generate it
                chunk = generateChunk(chunkX, chunkZ);
                loadedChunks.set(chunkKey, chunk);
                scene.add(chunk);
            }

            // Create and add the new block
            const block = new THREE.Mesh(blockGeometry, blockMaterial);
            block.position.copy(position);
            chunk.add(block);

            // Update debug info with block placement details
            document.getElementById('debug').textContent += `\nPlaced block at (${position.x}, ${position.y}, ${position.z})`;
        }

        // Event listeners for keyboard
        document.addEventListener('keydown', (e) => {
            const key = e.key.toLowerCase();
            if (['w', 'a', 's', 'd', ' '].includes(key)) {
                keys[key] = true;
            }
        });
        document.addEventListener('keyup', (e) => {
            const key = e.key.toLowerCase();
            if (['w', 'a', 's', 'd', ' '].includes(key)) {
                keys[key] = false;
            }
        });

        // Event listener for mouse clicks
        document.addEventListener('mousedown', (e) => {
            if (document.pointerLockElement === document.body) {
                // Update mouse coordinates for raycasting
                mouse.x = 0;
                mouse.y = 0;

                raycaster.setFromCamera(mouse, camera);
                
                // Gather all block meshes
                const allBlocks = Array.from(loadedChunks.values()).flatMap(chunk => chunk.children);
                
                // Find intersections
                const intersects = raycaster.intersectObjects(allBlocks, false);

                if (intersects.length > 0) {
                    if (e.button === 0) { // Left click - remove block
                        const intersectedBlock = intersects[0].object;
                        const blockPos = intersectedBlock.position;
                        intersectedBlock.parent.remove(intersectedBlock);
                        // Optionally, update debug info
                        document.getElementById('debug').textContent += `\nRemoved block at (${blockPos.x}, ${blockPos.y}, ${blockPos.z})`;
                    } else if (e.button === 2) { // Right click - add block
                        placeBlock(intersects[0].point, intersects[0].face.normal);
                    }
                }
            }
        });

        // Event listener for mouse movement
        document.addEventListener('mousemove', (e) => {
            if (document.pointerLockElement === document.body) {
                yaw -= e.movementX * 0.002;
                pitch -= e.movementY * 0.002;
                pitch = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, pitch));
            }
        });

        // Prevent context menu on right-click
        document.addEventListener('contextmenu', (e) => e.preventDefault());

        // Request pointer lock on canvas click
        renderer.domElement.addEventListener('click', () => {
            document.body.requestPointerLock();
        });

        // Function to find the highest block at given (x, z)
        function getHighestBlockY(x, z) {
            const blockX = Math.floor(x);
            const blockZ = Math.floor(z);
            let highestY = -Infinity;

            loadedChunks.forEach(chunk => {
                // Only check blocks in the relevant chunk
                chunk.children.forEach(block => {
                    if (Math.floor(block.position.x) === blockX && Math.floor(block.position.z) === blockZ) {
                        if (block.position.y > highestY) {
                            highestY = block.position.y;
                        }
                    }
                });
            });

            return highestY;
        }

        // Animation loop
        function animate() {
            requestAnimationFrame(animate);

            // Handle movement
            let moveX = 0;
            let moveZ = 0;
            if (keys['w']) {
                moveX -= Math.sin(yaw) * player.speed;
                moveZ -= Math.cos(yaw) * player.speed;
            }
            if (keys['s']) {
                moveX += Math.sin(yaw) * player.speed;
                moveZ += Math.cos(yaw) * player.speed;
            }
            if (keys['a']) {
                moveX -= Math.cos(yaw) * player.speed;
                moveZ += Math.sin(yaw) * player.speed;
            }
            if (keys['d']) {
                moveX += Math.cos(yaw) * player.speed;
                moveZ -= Math.sin(yaw) * player.speed;
            }

            player.position.x += moveX;
            player.position.z += moveZ;

            if (keys[' '] && player.onGround) {
                player.velocity.y = player.jumpForce;
                player.onGround = false;
            }

            // Apply gravity
            if (!player.onGround) {
                player.velocity.y -= 0.015;
            }
            player.position.y += player.velocity.y;

            // Improved Collision detection with actual blocks
            const highestBlockY = getHighestBlockY(player.position.x, player.position.z);
            if (highestBlockY !== -Infinity) {
                const playerFeetY = player.position.y;
                const desiredY = highestBlockY + 1; // Player stands on top of the block

                // Check if the player is below the desired position (within a small threshold)
                if (playerFeetY < desiredY) {
                    player.position.y = desiredY;
                    player.velocity.y = 0;
                    player.onGround = true;
                } else {
                    player.onGround = false;
                }
            } else {
                // No blocks found below, player is in the air
                player.onGround = false;
            }

            // Update chunks based on player position
            loadChunksAroundPosition(player.position);

            // Update camera position and rotation
            camera.position.copy(player.position);
            camera.position.y += 1.6; // Eye height
            camera.rotation.order = 'YXZ';
            camera.rotation.y = yaw;
            camera.rotation.x = pitch;

            renderer.render(scene, camera);
        }

        // Handle window resize
        window.addEventListener('resize', () => {
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            renderer.setSize(window.innerWidth, window.innerHeight);
        });

        animate();
    </script>
</body>
</html>