in this code, the movement is completely borked. it tries to move, but it looks like it gets cancelled. completely rewrite how movement is handled. give the full updated code

const mineflayer = require('mineflayer');
const { pathfinder, Movements, goals } = require('mineflayer-pathfinder');
const express = require('express');
const Vec3 = require('vec3');
const { GoalBlock, GoalXZ, GoalNear } = goals;

const app = express();
const port = 8000;

// Bot configuration
const botConfig = {
  host: 'localhost',
  port: 25565,
  username: 'ChunkScanner',
  version: '1.18.2'
};

// Optimization: Use Set for O(1) lookups
const transparentBlocks = new Set([
  'air', 'water', 'lava', 'chain', 'grass_block', 'grass', 'tall_grass'
]);

// Optimization: Compile patterns into a single regex for faster matching
const transparentBlockPattern = new RegExp(
  '(glass|leaves|fence|door|trapdoor|bars|rod|lantern|vine|sapling|coral|kelp|' +
  'bamboo|mushroom|rail|torch|sign|banner|button|pressure|carpet|ladder)'
);

// Cache frequently accessed values
const CHUNK_SIZE = 16;
const CHUNK_RANGE = { X: 3, Z: 3 };
const ENABLE_CULLING = true;

// Preallocate vectors for better memory usage
const NEIGHBOR_OFFSETS = [
  new Vec3(1, 0, 0), new Vec3(-1, 0, 0),
  new Vec3(0, 1, 0), new Vec3(0, -1, 0),
  new Vec3(0, 0, 1), new Vec3(0, 0, -1)
];

// State management
let bot;
let chunksLoaded = false;
let chunkCache = new Map();
let cachedBlockData = [];
let currentMovementTimeout = null;
let isMoving = false;

// Configure express to parse JSON
app.use(express.json());

// Optimization: Use faster lookup for transparent blocks
function isTransparentBlock(blockName) {
  return transparentBlocks.has(blockName) || transparentBlockPattern.test(blockName);
}

function isBlockExposed(bot, blockPos) {
  for (const offset of NEIGHBOR_OFFSETS) {
    const neighborPos = blockPos.plus(offset);
    const neighborBlock = bot.blockAt(neighborPos);
    if (!neighborBlock || isTransparentBlock(neighborBlock.name)) {
      return true;
    }
  }
  return false;
}

// Scan loaded chunks and cache block data
function scanLoadedChunks(bot) {
  const blocks = [];
  const world = bot.world;
  const playerPos = bot.entity.position;
  
  const playerChunk = {
    x: Math.floor(playerPos.x / CHUNK_SIZE),
    z: Math.floor(playerPos.z / CHUNK_SIZE)
  };

  const minY = world.minY || 0;
  const maxY = world.maxY || 256;
  const blockPos = new Vec3(0, 0, 0); // Reuse Vec3 instance

  const batchSize = 4;
  for (let cx = -CHUNK_RANGE.X; cx <= CHUNK_RANGE.X; cx += batchSize) {
    for (let cz = -CHUNK_RANGE.Z; cz <= CHUNK_RANGE.Z; cz += batchSize) {
      processChunkBatch(cx, cz, Math.min(batchSize, CHUNK_RANGE.X - cx + 1), 
                       Math.min(batchSize, CHUNK_RANGE.Z - cz + 1));
    }
  }

  function processChunkBatch(startCX, startCZ, batchWidth, batchHeight) {
    for (let cx = startCX; cx < startCX + batchWidth; cx++) {
      for (let cz = startCZ; cz < startCZ + batchHeight; cz++) {
        const chunkX = playerChunk.x + cx;
        const chunkZ = playerChunk.z + cz;
        
        for (let x = 0; x < CHUNK_SIZE; x++) {
          for (let z = 0; z < CHUNK_SIZE; z++) {
            const absoluteX = chunkX * CHUNK_SIZE + x;
            const absoluteZ = chunkZ * CHUNK_SIZE + z;
            
            if (Math.abs(absoluteX - playerPos.x) > CHUNK_SIZE * CHUNK_RANGE.X ||
                Math.abs(absoluteZ - playerPos.z) > CHUNK_SIZE * CHUNK_RANGE.Z) {
              continue;
            }

            for (let y = minY; y < maxY; y++) {
              try {
                blockPos.set(absoluteX, y, absoluteZ);
                const block = bot.blockAt(blockPos);
                
                if (!block || block.type === 0) continue;

                if (isTransparentBlock(block.name)) {
                  blocks.push({
                    block_name: block.name,
                    x: absoluteX,
                    y,
                    z: absoluteZ,
                    direction: block.metadata
                  });
                  continue;
                }
                
                if (ENABLE_CULLING && y < playerPos.y && !isBlockExposed(bot, blockPos)) {
                  continue;
                }
                
                blocks.push({
                  block_name: block.name,
                  x: absoluteX,
                  y,
                  z: absoluteZ,
                  direction: block.metadata
                });
              } catch (err) {
                continue;
              }
            }
          }
        }
      }
    }
  }
  
  return blocks;
}

// Start bot and listen for chunk loading
function initializeBot() {
  bot = mineflayer.createBot(botConfig);
  
  // Load the pathfinder plugin
  bot.loadPlugin(pathfinder);
  
  bot.once('spawn', () => {
    // Initialize movements with default values
    const movements = new Movements(bot);
    bot.pathfinder.setMovements(movements);
    console.log('Bot spawned, waiting for chunks to load...');
  });

  bot.on('chunkColumnLoad', (point) => {
    if (!chunksLoaded) {
      chunksLoaded = true;
      console.log('First chunk loaded at', point);
      setTimeout(() => {
        cachedBlockData = scanLoadedChunks(bot);
        console.log(`Scanned ${cachedBlockData.length} blocks`);
        chunkCache.clear(); // Free memory
      }, 2000);
    }
  });

  // Add physics tick handler for smooth movement
  bot.on('physicsTick', () => {
    if (isMoving) {
      // Refresh the timeout to prevent premature stopping
      if (currentMovementTimeout) {
        clearTimeout(currentMovementTimeout);
        currentMovementTimeout = setTimeout(() => {
          bot.clearControlStates();
          isMoving = false;
        }, 200);
      }
    }
  });

  bot.on('error', console.error);
  bot.on('kicked', console.log);
}

// API Endpoints
app.get('/blocks', (req, res) => {
  res.json(cachedBlockData);
});

// Get the current coordinates of the bot
app.get('/bot/coordinates', (req, res) => {
  if (bot && bot.entity) {
    const position = bot.entity.position;
    res.json({
      x: position.x,
      y: position.y,
      z: position.z
    });
  } else {
    res.status(404).json({
      success: false,
      error: 'Bot is not available'
    });
  }
});

// Set bot coordinates using pathfinding
app.post('/bot/coordinates', express.json(), (req, res) => {
  const { x, y, z } = req.body;
  if (bot) {
    try {
      // Use pathfinding to move to the target position
      bot.pathfinder.setGoal(new GoalBlock(x, y, z));
      
      res.json({
        success: true,
        message: `Bot pathfinding to ${x}, ${y}, ${z}`
      });
    } catch (err) {
      res.status(500).json({
        success: false,
        error: err.message
      });
    }
  } else {
    res.status(404).json({
      success: false,
      error: 'Bot is not available'
    });
  }
});

// Modified movement endpoint with improved state management
app.post('/bot/move', express.json(), (req, res) => {
  const { action, jump, sprint } = req.body;
  if (bot) {
    try {
      // Clear any existing movement timeout
      if (currentMovementTimeout) {
        clearTimeout(currentMovementTimeout);
      }

      // Clear previous movement states only if not currently moving
      if (!isMoving) {
        bot.clearControlStates();
      }
      
      isMoving = action !== 'none';
      
      // Set control states based on action
      switch(action) {
        case 'forward':
          bot.setControlState('forward', true);
          if (sprint) bot.setControlState('sprint', true);
          break;
        case 'backward':
          bot.setControlState('back', true);
          break;
        case 'left':
          bot.setControlState('left', true);
          break;
        case 'right':
          bot.setControlState('right', true);
          break;
        case 'none':
          bot.clearControlStates();
          isMoving = false;
          break;
      }
      
      if (jump) {
        bot.setControlState('jump', true);
      }
      
      // Set a timeout to clear movement states if no new movement command is received
      if (isMoving) {
        currentMovementTimeout = setTimeout(() => {
          bot.clearControlStates();
          isMoving = false;
        }, 200); // Adjust this value based on your needs
      }
      
      res.json({
        success: true,
        message: `Bot moving ${action}, Jump: ${jump}, Sprint: ${sprint}`,
        isMoving: isMoving
      });
    } catch (err) {
      res.status(500).json({
        success: false,
        error: err.message
      });
    }
  } else {
    res.status(404).json({
      success: false,
      error: 'Bot is not available'
    });
  }
});

// Set bot's head look position
app.post('/bot/look', express.json(), (req, res) => {
  const { x, y, z } = req.body;
  if (bot) {
    try {
      const targetPosition = new Vec3(x, y, z);
      bot.lookAt(targetPosition, true, () => {
        res.json({
          success: true,
          message: `Bot looking at ${x}, ${y}, ${z}`
        });
      });
    } catch (err) {
      res.status(500).json({
        success: false,
        error: err.message
      });
    }
  } else {
    res.status(404).json({
      success: false,
      error: 'Bot is not available'
    });
  }
});

// Start the server
app.listen(port, () => {
  console.log(`Server listening on port ${port}`);
  initializeBot();
});