import * as mc from "@minecraft/server";
import * as vector from "../utils/vector";
import * as boulder from "../entities/boulderProjectile";
import * as utils from "../utils/generalUtils";

const timeToUse = 10000 * 20; // Total ticks to complete the use of the Earthrend Gauntlet (defined in the item BP)

export function startUsing(event) {
  const { itemStack, source } = event;

  if (itemStack && itemStack.typeId === "hf_mzs:earthrend_gauntlet") {
    mc.system.run(() => {
      // dont play summoning boulder animation
      const lookAt = source.getBlockFromViewDirection({
        maxDistance: 7,
        includePassableBlocks: false,
        includeLiquidBlocks: false,
        excludeTypes: boulder.excludedBlocks,
      });
      let up1, up2;
      if (lookAt && lookAt.block && lookAt.block.isValid()) {
        up1 = lookAt.block.above();
        if (up1 && up1 && up1.isValid()) {
          up2 = up1.above();
        }
      }

      // this is so messy but I really don't feel like rewriting it
      if (source.isSneaking) {
        if (
          !lookAt ||
          !lookAt.block ||
          !lookAt.block.isValid() ||
          lookAt.block.isAir ||
          lookAt.block.isLiquid ||
          lookAt.face !== "Up" ||
          (lookAt && lookAt.block && !GeomancyWhitelist.includes(lookAt.block.typeId))
        ) {
          mc.system.run(() => {
            source.onScreenDisplay.setActionBar({ translate: "dialogue.hf_mzs.earthrend_gauntlet.boulder_hint" });
          });
          event.cancel = true;
          return;
        }

        if (
          !up1 ||
          !up1.isValid() ||
          (!up1.isAir && !up1.isLiquid && !PassableBlocks.includes(up1.typeId)) ||
          !up2 ||
          !up2.isValid() ||
          (!up2.isAir && !up2.isLiquid && !PassableBlocks.includes(up2.typeId))
        ) {
          mc.system.run(() => {
            source.onScreenDisplay.setActionBar({ translate: "dialogue.hf_mzs.earthrend_gauntlet.boulder_no_space" });
          });
          event.cancel = true;
          return;
        }
      }

      if (source.isSneaking) {
        source.addTag("hf_mzs_using_earthrend_ground");
        source.setDynamicProperty("hf_mzs:earthrend_ground_tick", 0);
        let type = "stone";
        let bl = lookAt.block;

        if (SandTypes.includes(bl.typeId)) type = "sandstone";
        else if (RedSandTypes.includes(bl.typeId)) type = "red_sandstone";
        else if (bl.typeId == "minecraft:clay") type = "clay";
        else if (bl.typeId == "minecraft:gravel" || bl.typeId == "minecraft:suspicious_gravel") type = "gravel";
        else if (DirtTypes.includes(bl.typeId)) type = "dirt";
        else if (AndesiteTypes.includes(bl.typeId)) type = "andesite";
        else if (GraniteTypes.includes(bl.typeId)) type = "granite";
        else if (DioriteTypes.includes(bl.typeId)) type = "diorite";
        else if (TuffTypes.includes(bl.typeId)) type = "tuff";
        else if (DeepslateTypes.includes(bl.typeId)) type = "deepslate";
        else if (CobbledDeepslateTypes.includes(bl.typeId)) type = "cobbled_deepslate";
        else if (CobblestoneTypes.includes(bl.typeId)) type = "cobblestone";
        else if (bl.typeId == "minecraft:dripstone_block") type = "dripstone";
        source.setDynamicProperty("hf_mzs:earthrend_boulder_type", type);

        source.playAnimation("animation.hf_mzs.earthrend_gauntlet.spawn_boulder_start", {
          stopExpression: "v.is_first_person",
        });
        disableCamera(source);
        return;
      } else {
        saveArea(source);
        source.removeTag("hf_mzs_underground");
        source.setDynamicProperty("hf_mzs:earthrend_digging", false);
        source.addTag("hf_mzs_using_earthrend_air");
        source.addTag("hf_mzs_using_earthrend");
        source.setDynamicProperty("hf_mzs:earthrend_air_tick", 0);
        source.setDynamicProperty("hf_mzs:earthrend_damage", 0);
        source.setDynamicProperty("hf_mzs:earthrend_should_launch", false);
        source.setDynamicProperty("hf_mzs:gauntlet_dug_deep", false);
        const remainingDurability =
          itemStack.getComponent("minecraft:durability").maxDurability -
          itemStack.getComponent("minecraft:durability").damage;
        source.setDynamicProperty("hf_mzs:earthrend_timer", remainingDurability);
        source.setDynamicProperty("hf_mzs:earthrend_start_y", source.location.y);
        source.onScreenDisplay.setHudVisibility(mc.HudVisibility.Hide, [mc.HudElement.StatusEffects]);

        const ground = source.dimension.getBlockFromRay(source.location, vector.down, {
          includeLiquidBlocks: false,
          includePassableBlocks: false,
        });

        if (ground && vector.distance(source.location, vector.add(ground.block.location, ground.faceLocation)) > 0) {
          if (source.getViewDirection().y < 0) source.setDynamicProperty("hf_mzs:earthrend_mid_air", true);
        } else source.setDynamicProperty("hf_mzs:earthrend_mid_air", false);
      }
    });
  }
}

export function stopUsing(event) {
  const { itemStack, useDuration, source } = event;

  if (itemStack && itemStack.typeId === "hf_mzs:earthrend_gauntlet") {
    mc.system.run(() => {
      if (source.hasTag("hf_mzs_using_earthrend_ground")) {
        spawnBoulder(source, useDuration);
      }
      if (source.hasTag("hf_mzs_using_earthrend_air")) {
        source.removeTag("hf_mzs_using_earthrend");
        source.setDynamicProperty("hf_mzs:earthrend_damage", timeToUse - useDuration);
        stopDigging(source);
      }
    });
  }
}

function spawnBoulder(source, useDuration) {
  source.removeTag("hf_mzs_using_earthrend_ground");
  source.playAnimation("animation.hf_mzs.earthrend_gauntlet.spawn_boulder_end", {
    stopExpression: "v.is_first_person",
  });
  enableMovement(source);
  enableCamera(source);
  source.removeEffect("slowness");
  source.onScreenDisplay.setHudVisibility(mc.HudVisibility.Reset, [mc.HudElement.StatusEffects]);

  const lookAt = source.getBlockFromViewDirection({
    maxDistance: 7,
    includePassableBlocks: false,
    includeLiquidBlocks: false,
    excludeTypes: boulder.excludedBlocks,
  });

  const testLoc = lookAt.block.above().above().location;
  testLoc.x = Math.floor(testLoc.x) + 0.5;
  testLoc.y = Math.floor(testLoc.y) + 0.5;
  testLoc.z = Math.floor(testLoc.z) + 0.5;
  const boulders = source.dimension.getEntities({ type: "hf_mzs:boulder", location: testLoc, maxDistance: 1 });
  if (boulders.length > 0 || source.hasTag("hf_mzs_cancel_boulder")) {
    source.runCommand("/stopsound @s hf_mzs:boulder_spawn_charge");
    source.removeTag("hf_mzs_cancel_boulder");
    return;
  }

  const mainHand = source.getComponent("equippable").getEquipment(mc.EquipmentSlot.Mainhand);
  if (mainHand && mainHand.typeId === "hf_mzs:earthrend_gauntlet" && source.getGameMode() != mc.GameMode.creative) {
    if (
      mainHand.getComponent("minecraft:durability").damage <
      mainHand.getComponent("minecraft:durability").maxDurability - 1
    ) {
      mainHand.getComponent("minecraft:durability").damage = mainHand.getComponent("minecraft:durability").damage + 1;
      source.getComponent("equippable").setEquipment(mc.EquipmentSlot.Mainhand, mainHand);
    }
  }

  let pPos = source.location;
  let pDir = vector.normalize(source.getViewDirection());
  pDir = vector.multiply(pDir, 3);
  pDir.y = 0;
  pPos = vector.add(pPos, pDir);
  let variant = 0;
  let timeout = 0;
  let size;
  let offset = 1;
  let radius = 1;
  let tpY = 1;
  let type = source.getDynamicProperty("hf_mzs:earthrend_boulder_type");
  source.setDynamicProperty("hf_mzs:earthrend_boulder_type", undefined);

  if (timeToUse - useDuration < 10) {
    variant = 0;
    timeout = 4;
    size = "small";
    radius = 1;
    tpY = 0.6;
    offset = 1;
    source.runCommand("/stopsound @s hf_mzs:boulder_spawn_charge");
  } else if (timeToUse - useDuration < 30) {
    variant = 1;
    timeout = 7;
    size = "medium";
    radius = 1.5;
    tpY = 0.6;
    source.runCommand("/stopsound @s hf_mzs:boulder_spawn_charge");
  } else if (timeToUse - useDuration < 50) {
    variant = 2;
    timeout = 10;
    size = "large";
    radius = 2;
    tpY = 0.75;
    source.runCommand("/stopsound @s hf_mzs:boulder_spawn_charge");
  } else {
    variant = 3;
    timeout = 80;
    size = "huge";
    radius = 2.5;
  }

  let map = new mc.MolangVariableMap();
  map.setFloat("variable.lifetime", 0.4);
  map.setFloat("variable.size", 1.0);

  if (lookAt && lookAt.block && lookAt.block.isValid()) {
    let bPos = lookAt.block.above().location;
    bPos.x = Math.floor(bPos.x) + 0.5;
    bPos.y += offset;
    bPos.z = Math.floor(bPos.z) + 0.5;

    let parPos = lookAt.block.above().location;
    parPos.x = Math.floor(parPos.x) + 0.5;
    parPos.z = Math.floor(parPos.z) + 0.5;

    source.dimension.spawnParticle("hf_mzs:ring_grow_ground", parPos, map);

    const b = source.dimension.spawnEntity(`hf_mzs:boulder<hf_mzs:${type}_${size}>`, bPos);
    b.setDynamicProperty("hf_mzs:owner", source.id);

    const entities = b.dimension.getEntities({
      location: b.location,
      maxRadius: radius,
      excludeTypes: ["hf_mzs:boulder", "minecraft:item", "minecraft:armor_stand"],
    });
    for (const en of entities) {
      if (vector.distance(en.location, parPos) <= radius) {
        if (size !== "huge") en.applyKnockback(0, 0, 0, tpY);
        else {
          mc.system.runTimeout(() => {
            en.addTag("hf_mzs_giant_boulder_rising");
            mc.system.runTimeout(() => {
              en.removeTag("hf_mzs_giant_boulder_rising");
            }, 70);
          }, 10);
        }
      }
    }

    mc.system.runTimeout(() => {
      boulder.fillBlocks(b, variant);
    }, timeout);
  }
}

async function stopDigging(source) {
  if (!isUnderground(source)) {
    await unstuckEntity(source);

    saveArea(source);
    digHole(source);

    mc.system.runTimeout(() => {
      const mainHand = source.getComponent("equippable").getEquipment(mc.EquipmentSlot.Mainhand);
      if (
        mainHand &&
        mainHand.typeId === "hf_mzs:earthrend_gauntlet" &&
        source.getGameMode() != mc.GameMode.spectator &&
        source.getGameMode() != mc.GameMode.creative
      ) {
        const remainingDurability =
          mainHand.getComponent("minecraft:durability").maxDurability -
          mainHand.getComponent("minecraft:durability").damage;
        const useDuration = parseFloat(source.getDynamicProperty("hf_mzs:earthrend_damage"));
        let dmg = remainingDurability - useDuration <= 0 ? remainingDurability - 1 : useDuration;
        mainHand.getComponent("minecraft:durability").damage =
          mainHand.getComponent("minecraft:durability").damage + dmg;
        source.getComponent("equippable").setEquipment(mc.EquipmentSlot.Mainhand, mainHand);
      }

      source.removeTag("hf_mzs_underground");
      if (
        source.getDynamicProperty("hf_mzs:earthrend_air_tick") > 0 &&
        source.getDynamicProperty("hf_mzs:earthrend_digging")
      ) {
        let pDir = vector.normalize(source.getViewDirection());
        source.playSound("hf_mzs:earthrend_emmerge", { volume: 1.0, pitch: 0.9 });
        const vDir = utils.map(pDir.y, -1, 1, 0.5, 1);
        const hDir = utils.map(vDir, 0.5, 1, 2, 1);
        if (source.getDynamicProperty("hf_mzs:earthrend_should_launch"))
          source.applyKnockback(pDir.x, pDir.z, hDir, vDir);
        source.addEffect("resistance", 999999, { amplifier: 255, showParticles: false });
        source.addTag("hf_mzs_fall_damage_off");
      }

      source.runCommand("/stopsound @s hf_mzs:earthrend_digging");
      enableMovement(source);
      source.setDynamicProperty("hf_mzs:earthrend_digging", false);
      source.removeTag("hf_mzs_using_earthrend_air");
      source.onScreenDisplay.setHudVisibility(mc.HudVisibility.Reset, [mc.HudElement.StatusEffects]);

      mc.system.runTimeout(() => {
        let pl = source.getDynamicProperty("hf_mzs:earthrend_prev_loc");
        if (pl) {
          pl = pl.split(",");
          let prevLoc = { x: parseFloat(pl[0]), y: parseFloat(pl[1]), z: parseFloat(pl[2]) };
          source.runCommandAsync(`structure load "hf_mzs.${source.id}" ${prevLoc.x} ${prevLoc.y} ${prevLoc.z}`);
        }

        source.runCommand(`/kill @e[type=item,r=5]`);

        source.setDynamicProperty("hf_mzs:earthrend_prev_loc", undefined);
        source.runCommandAsync(`structure delete "hf_mzs.${source.id}"`);

        mc.system.runTimeout(() => {
          if (unstuckEntity(source)) {
            let pDir = vector.normalize(source.getViewDirection());
            const vDir = utils.map(pDir.y, -1, 1, 0.5, 1);
            const hDir = utils.map(vDir, 0.5, 1, 2, 1);
            if (source.getDynamicProperty("hf_mzs:earthrend_should_launch"))
              source.applyKnockback(pDir.x, pDir.z, hDir, vDir);
            mc.system.runTimeout(() => {
              source.addEffect("resistance", 999999, { amplifier: 255, showParticles: false });
              source.addTag("hf_mzs_fall_damage_off");
            }, 15);
          }
        }, 1);
      }, 1);
    }, 1);
  } else {
    source.addTag("hf_mzs_underground");
  }
}

function stopDiggingInstant(player) {
  const inventory = player.getComponent("inventory");
  if (!inventory || !inventory.container) return;
  const { container } = inventory;
  for (let i = 0; i <= inventory.inventorySize - 1; i++) {
    const itemSearch = container.getItem(i);
    if (itemSearch === undefined) continue;
    if (
      itemSearch &&
      itemSearch.typeId === "hf_mzs:earthrend_gauntlet" &&
      player.getGameMode() != mc.GameMode.spectator &&
      player.getGameMode() != mc.GameMode.creative
    ) {
      const remainingDurability =
        itemSearch.getComponent("minecraft:durability").maxDurability -
        itemSearch.getComponent("minecraft:durability").damage;
      const useDuration = parseFloat(player.getDynamicProperty("hf_mzs:earthrend_damage"));
      let dmg = remainingDurability - useDuration <= 0 ? remainingDurability - 1 : useDuration;
      itemSearch.getComponent("minecraft:durability").damage =
        itemSearch.getComponent("minecraft:durability").damage + dmg;
      container.setItem(i, itemSearch);
    }
  }

  player.removeTag("hf_mzs_using_earthrend");
  player.removeTag("hf_mzs_using_earthrend_air");
  player.setDynamicProperty("hf_mzs:earthrend_digging", false);
  player.runCommand("/stopsound @s hf_mzs:earthrend_digging");
  let pl = player.getDynamicProperty("hf_mzs:earthrend_prev_loc");
  if (pl) {
    pl = pl.split(",");
    let prevLoc = { x: parseFloat(pl[0]), y: parseFloat(pl[1]), z: parseFloat(pl[2]) };
    player.runCommandAsync(`structure load "hf_mzs.${player.id}" ${prevLoc.x} ${prevLoc.y} ${prevLoc.z}`);
  }

  player.runCommand(`/kill @e[type=item,r=5]`);

  player.setDynamicProperty("hf_mzs:earthrend_prev_loc", undefined);
  player.runCommandAsync(`structure delete "hf_mzs.${player.id}"`);

  mc.system.runTimeout(() => {
    if (unstuckEntity(player, true)) {
      player.playSound("hf_mzs:earthrend_emmerge", { volume: 1.0, pitch: 0.9 });
      let pDir = vector.normalize(player.getViewDirection());
      const vDir = utils.map(pDir.y, -1, 1, 0.5, 1);
      const hDir = utils.map(vDir, 0.5, 1, 2, 1);
      if (player.getDynamicProperty("hf_mzs:earthrend_should_launch"))
        player.applyKnockback(pDir.x, pDir.z, hDir, vDir);
      mc.system.runTimeout(() => {
        player.addEffect("resistance", 999999, { amplifier: 255, showParticles: false });
        player.addTag("hf_mzs_fall_damage_off");
      }, 15);
    }
  }, 1);
}

async function digHole(entity) {
  const center = entity.location;
  const radius = 3;

  const entities = entity.dimension.getEntities({ location: center, maxDistance: radius * 2 });
  for (let en of entities) {
    if (en.id !== entity.id) en.teleport(en.location);
  }

  for (let i = -radius; i <= radius; i++) {
    for (let j = -radius; j <= radius; j++) {
      for (let k = -radius; k <= radius; k++) {
        if (center.y + k <= entity.dimension.heightRange.min || center.y + k > entity.dimension.heightRange.max)
          continue;
        let block = entity.dimension.getBlock({ x: center.x + i, y: center.y + k, z: center.z + j });

        let dist = vector.distance(center, block);

        if (
          block &&
          block.isValid() &&
          (block.hasTag("stone") ||
            block.hasTag("dirt") ||
            block.hasTag("sand") ||
            block.hasTag("grass") ||
            block.hasTag("gravel") ||
            block.typeId.includes("snow") ||
            block.hasTag("diamond_pick_diggable") ||
            block.typeId.includes("stone") ||
            block.typeId.includes("deepslate") ||
            block.typeId.includes("terracotta") ||
            GeomancyWhitelist.includes(block.typeId)) &&
          dist < radius
        ) {
          if (entity.getDynamicProperty("hf_mzs:earthrend_digging"))
            block.setPermutation(mc.BlockPermutation.resolve("minecraft:air"));
        }
      }
    }
  }
}

async function saveArea(player) {
  let center = player.location;
  center.x = Math.floor(center.x);
  center.y = Math.floor(center.y);
  center.z = Math.floor(center.z);
  let offset = { x: 5, y: 5, z: 5 };
  let start = vector.subtract(center, offset);
  let end = vector.add(center, offset);

  let pl = player.getDynamicProperty("hf_mzs:earthrend_prev_loc");
  if (pl) {
    pl = pl.split(",");
    let prevLoc = { x: parseFloat(pl[0]), y: parseFloat(pl[1]), z: parseFloat(pl[2]) };
    player.runCommandAsync(`structure load "hf_mzs.${player.id}" ${prevLoc.x} ${prevLoc.y} ${prevLoc.z}`);
  }

  player.setDynamicProperty("hf_mzs:earthrend_prev_loc", `${start.x},${start.y},${start.z}`);

  player.runCommandAsync(
    `structure save "hf_mzs.${player.id}" ${start.x} ${start.y} ${start.z} ${end.x} ${end.y} ${end.z} false disk`
  );
}

export function disableMovement(player) {
  player.runCommand("/inputpermission set @s movement disabled");
}

export function enableMovement(player) {
  player.runCommand("/inputpermission set @s movement enabled");
}

export function disableCamera(player) {
  player.runCommand("/inputpermission set @s camera disabled");
}

export function enableCamera(player) {
  player.runCommand("/inputpermission set @s camera enabled");
}

export function isUnderground(entity, distance = 5) {
  const upVector = { x: 0, y: 1, z: 0 };

  const pos1 = entity.location;
  const pos2 = entity.location;
  pos2.x += 1;
  const pos3 = entity.location;
  pos3.x -= 1;
  const pos4 = entity.location;
  pos4.z += 1;
  const pos5 = entity.location;
  pos5.z -= 1;
  const pos6 = entity.location;
  pos6.x += 1;
  pos6.z += 1;
  const pos7 = entity.location;
  pos7.x -= 1;
  pos7.z -= 1;
  const pos8 = entity.location;
  pos8.x += 1;
  pos8.z -= 1;
  const pos9 = entity.location;
  pos9.x -= 1;
  pos9.z += 1;

  let rayCastHit1 = entity.dimension.getBlockFromRay(pos1, upVector, {
    maxDistance: distance,
    includePassableBlocks: false,
    includeLiquidBlocks: false,
    excludeTypes: boulder.excludedBlocks,
  });
  let rayCastHit2 = entity.dimension.getBlockFromRay(pos2, upVector, {
    maxDistance: distance,
    includePassableBlocks: false,
    includeLiquidBlocks: false,
    excludeTypes: boulder.excludedBlocks,
  });
  let rayCastHit3 = entity.dimension.getBlockFromRay(pos3, upVector, {
    maxDistance: distance,
    includePassableBlocks: false,
    includeLiquidBlocks: false,
    excludeTypes: boulder.excludedBlocks,
  });
  let rayCastHit4 = entity.dimension.getBlockFromRay(pos4, upVector, {
    maxDistance: distance,
    includePassableBlocks: false,
    includeLiquidBlocks: false,
    excludeTypes: boulder.excludedBlocks,
  });
  let rayCastHit5 = entity.dimension.getBlockFromRay(pos5, upVector, {
    maxDistance: distance,
    includePassableBlocks: false,
    includeLiquidBlocks: false,
    excludeTypes: boulder.excludedBlocks,
  });
  let rayCastHit6 = entity.dimension.getBlockFromRay(pos6, upVector, {
    maxDistance: distance,
    includePassableBlocks: false,
    includeLiquidBlocks: false,
    excludeTypes: boulder.excludedBlocks,
  });
  let rayCastHit7 = entity.dimension.getBlockFromRay(pos7, upVector, {
    maxDistance: distance,
    includePassableBlocks: false,
    includeLiquidBlocks: false,
    excludeTypes: boulder.excludedBlocks,
  });
  let rayCastHit8 = entity.dimension.getBlockFromRay(pos8, upVector, {
    maxDistance: distance,
    includePassableBlocks: false,
    includeLiquidBlocks: false,
    excludeTypes: boulder.excludedBlocks,
  });
  let rayCastHit9 = entity.dimension.getBlockFromRay(pos9, upVector, {
    maxDistance: distance,
    includePassableBlocks: false,
    includeLiquidBlocks: false,
    excludeTypes: boulder.excludedBlocks,
  });

  if (
    !rayCastHit1 &&
    !rayCastHit2 &&
    !rayCastHit3 &&
    !rayCastHit4 &&
    !rayCastHit5 &&
    !rayCastHit6 &&
    !rayCastHit7 &&
    !rayCastHit8 &&
    !rayCastHit9
  )
    return false;
  return true;
}

function boulderCanFit(player, variant) {
  const lookAt = player.getBlockFromViewDirection({
    maxDistance: 7,
    includePassableBlocks: false,
    includeLiquidBlocks: false,
    excludeTypes: boulder.excludedBlocks,
  });
  if (lookAt && lookAt.block && lookAt.block.isValid()) {
    let hSize = 1;
    let vSize = 1;
    switch (variant) {
      case 1:
        hSize = 1;
        vSize = 1;
        break;
      case 2:
        hSize = 1;
        vSize = 3;
        break;
      case 3:
        hSize = 2;
        vSize = 4;
        break;
    }

    const loc = lookAt.block.above().location;

    for (let i = -hSize; i <= hSize; i++) {
      for (let j = -hSize; j <= hSize; j++) {
        for (let k = 0; k < vSize; k++) {
          let bl = { x: loc.x + i, y: loc.y + k, z: loc.z + j };
          const block = player.dimension.getBlock(bl);
          if (!block || !block.isValid() || (!block.isAir && !block.isLiquid && !PassableBlocks.includes(block.typeId)))
            return false;
        }
      }
    }

    return true;
  }
}

export async function tick1() {
  mc.system.run(async () => {
    for (const player of mc.world.getAllPlayers()) {
      if (player.hasTag("hf_mzs_fall_damage_off") && player.isOnGround) {
        player.removeTag("hf_mzs_fall_damage_off");
        player.removeEffect("resistance");
      }
      if (player.getGameMode() === mc.GameMode.spectator) continue;
      // Boulder summoning
      if (player.hasTag("hf_mzs_using_earthrend_ground")) {
        const pVel = player.getVelocity();
        if (vector.magnitude(pVel) > 0.2) {
          player.addTag("hf_mzs_cancel_boulder");
          spawnBoulder(player, 0);
          continue;
        }
        const tickTime = player.getDynamicProperty("hf_mzs:earthrend_ground_tick");

        if (tickTime >= 2) {
          player.onScreenDisplay.setHudVisibility(mc.HudVisibility.Hide, [mc.HudElement.StatusEffects]);
          player.addEffect("slowness", 5, { amplifier: 2, showParticles: false });
        }

        if (tickTime === 0) player.playSound("hf_mzs:boulder_spawn_charge", { volume: 0.5, pitch: 1.0 });
        else if (tickTime === 50) {
          let map = new mc.MolangVariableMap();
          map.setFloat("variable.lifetime", 0.3);
          map.setFloat("variable.size", 2.0);
          player.dimension.spawnParticle("hf_mzs:ring_grow_ground", player.location, map);
        } else if (tickTime === 60) {
          spawnBoulder(player, timeToUse - tickTime);
        }

        if (tickTime === 0) {
          if (!boulderCanFit(player, 1)) spawnBoulder(player, timeToUse - tickTime + 5);
        } else if (tickTime === 11) {
          if (!boulderCanFit(player, 2)) spawnBoulder(player, timeToUse - tickTime + 5);
        } else if (tickTime === 31) {
          if (!boulderCanFit(player, 3)) spawnBoulder(player, timeToUse - tickTime + 5);
        }

        if (tickTime > 0 && tickTime < 50 && tickTime % 15 === 0) {
          let map = new mc.MolangVariableMap();
          map.setFloat("variable.lifetime", 0.3);
          map.setFloat("variable.size", 2.0);
          player.dimension.spawnParticle("hf_mzs:ring_shrink_ground", player.location, map);
        }

        player.setDynamicProperty("hf_mzs:earthrend_ground_tick", tickTime + 1);
      }

      // Digging
      if (player.hasTag("hf_mzs_using_earthrend_air")) {
        const tickTime = player.getDynamicProperty("hf_mzs:earthrend_air_tick");

        const mainHand = player.getComponent("equippable").getEquipment(mc.EquipmentSlot.Mainhand);
        if (!mainHand || mainHand.typeId !== "hf_mzs:earthrend_gauntlet") {
          player.setDynamicProperty("hf_mzs:earthrend_damage", tickTime);
          // mc.world.sendMessage("Stopped digging 1");
          stopDiggingInstant(player);
          return;
        }

        const maxDurability = mainHand.getComponent("minecraft:durability").maxDurability;
        let currentDurability = mainHand.getComponent("minecraft:durability").damage + tickTime;
        player.setDynamicProperty("hf_mzs:earthrend_damage", currentDurability);

        if (player.getGameMode() != mc.GameMode.creative && currentDurability > maxDurability) {
          currentDurability = maxDurability;
          player.setDynamicProperty("hf_mzs:earthrend_damage", currentDurability);
          // mc.world.sendMessage("Stopped digging 2");
          stopDigging(player);
        }

        if (player.getGameMode() != mc.GameMode.creative && player.hasTag("hf_mzs_using_earthrend")) {
          player.onScreenDisplay.setActionBar({
            rawtext: [
              { translate: "message.hf_mzs.gauntlet_durability" },
              { text: `${100 - Math.round((currentDurability / maxDurability) * 100)}%` },
            ],
          });
        }

        let pDir = player.getViewDirection();

        const ground = player.dimension.getBlockFromRay(player.location, vector.down, {
          includeLiquidBlocks: false,
          includePassableBlocks: false,
        });

        if (
          (ground && vector.distance(player.location, vector.add(ground.block.location, ground.faceLocation)) === 0) ||
          player.getDynamicProperty("hf_mzs:earthrend_mid_air")
        ) {
          if (tickTime === 0 && !player.getDynamicProperty("hf_mzs:earthrend_mid_air"))
            player.applyKnockback(0, 0, 0, 0.5);

          if (tickTime > 0) {
            player.setDynamicProperty("hf_mzs:earthrend_digging", true);
          }
        }

        if (player.getDynamicProperty("hf_mzs:earthrend_digging")) {
          let startY = player.getDynamicProperty("hf_mzs:earthrend_start_y");
          let currY = player.location.y;
          if (!isUnderground(player) && tickTime > 10) {
            if (currY > startY) {
              player.setDynamicProperty("hf_mzs:earthrend_damage", tickTime);
              stopDiggingInstant(player);
            }
          } else if (
            !isUnderground(player) &&
            currY > startY &&
            !player.getDynamicProperty("hf_mzs:earthrend_mid_air") &&
            !player.hasTag("hf_mzs_using_earthrend")
          ) {
            player.setDynamicProperty("hf_mzs:gauntlet_dug_deep", false);
            player.removeTag("hf_mzs_underground");
            // mc.world.sendMessage("Stopped digging 3");
            stopDigging(player);
          } else if (
            player.getDynamicProperty("hf_mzs:gauntlet_dug_deep") &&
            !isUnderground(player) &&
            !player.hasTag("hf_mzs_using_earthrend")
          ) {
            player.setDynamicProperty("hf_mzs:gauntlet_dug_deep", false);
            player.removeTag("hf_mzs_underground");
            player.setDynamicProperty("hf_mzs:earthrend_damage", tickTime);
            // mc.world.sendMessage("Stopped digging 4");
            stopDigging(player);
          } else if (player.getDynamicProperty("hf_mzs:gauntlet_dug_deep") && !isUnderground(player)) {
            player.setDynamicProperty("hf_mzs:gauntlet_dug_deep", false);
            player.removeTag("hf_mzs_underground");
            player.setDynamicProperty("hf_mzs:earthrend_damage", tickTime);
            // mc.world.sendMessage("Stopped digging 4");
            stopDigging(player);
          }

          if (tickTime >= player.getDynamicProperty("hf_mzs:earthrend_timer")) {
            player.setDynamicProperty("hf_mzs:earthrend_damage", player.getDynamicProperty("hf_mzs:earthrend_timer"));
            // mc.world.sendMessage("Stopped digging 5");
            stopDigging(player);
          }

          if (currY < startY - 5 && isUnderground(player)) player.setDynamicProperty("hf_mzs:gauntlet_dug_deep", true);
          if (tickTime > 10 || currY < startY - 5) player.setDynamicProperty("hf_mzs:earthrend_should_launch", true);

          if (tickTime % 13 === 0) player.playSound("hf_mzs:earthrend_digging", { volume: 0.2, pitch: 1.1 });
          if (tickTime % 20 === 0)
            player.playAnimation("animation.hf_mzs.earthrend_gauntlet.tunneling_drill", {
              stopExpression: "v.is_first_person",
            });

          let horizontalSpeed = Math.sqrt(pDir.x * pDir.x + pDir.z * pDir.z) * 0.3;
          let verticalSpeed = pDir.y * 0.175;
          if (player.hasTag("hf_mzs_underground")) verticalSpeed = 0.3;
          player.applyKnockback(pDir.x, pDir.z, horizontalSpeed, verticalSpeed);

          await saveArea(player);

          await digHole(player);

          player.runCommand(`/kill @e[type=item,r=5]`);
        }

        player.setDynamicProperty("hf_mzs:earthrend_air_tick", tickTime + 1);
      }
    }

    const getEntities = mc.world.getDimension("overworld").getEntities({ tags: ["hf_mzs_giant_boulder_rising"] });
    const getEntitiesN = mc.world.getDimension("nether").getEntities({ tags: ["hf_mzs_giant_boulder_rising"] });
    const getEntitiesE = mc.world.getDimension("the_end").getEntities({ tags: ["hf_mzs_giant_boulder_rising"] });

    getEntities.push(...getEntitiesN, ...getEntitiesE);

    for (const entity of getEntities) {
      // Giant boulder rising
      if (entity.hasTag("hf_mzs_giant_boulder_rising")) {
        entity.applyKnockback(0, 0, 0, 0.076);
      }
    }
  });
}

export function tick100() {
  for (const player of mc.world.getAllPlayers()) {
    // Gauntlet recharge
    if (!player.hasTag("hf_mzs_using_earthrend_air")) {
      const inventory = player.getComponent("inventory");
      if (!inventory || !inventory.container) return;
      const { container } = inventory;
      for (let i = 0; i <= inventory.inventorySize - 1; i++) {
        const itemSearch = container.getItem(i);
        if (itemSearch === undefined) continue;
        if (itemSearch.typeId === "hf_mzs:earthrend_gauntlet") {
          if (itemSearch.getComponent("minecraft:durability").damage > 0) {
            const targetDamage = itemSearch.getComponent("minecraft:durability").damage - 50;
            itemSearch.getComponent("minecraft:durability").damage = targetDamage < 0 ? 0 : targetDamage;
            container.setItem(i, itemSearch);
          }
        }
      }
    }
  }
}

export async function unstuckEntity(player, onlyCheckUp) {
  let dim = player.dimension;
  let source = dim.getBlock(player.location);
  if (!source) return;
  if (source.isAir || source.typeId === "minecraft:water") return;

  let unstuck = false;
  let iterations = 0;

  while (!unstuck) {
    iterations++;

    let up = dim.getBlock({ x: source.x, y: source.y + iterations, z: source.z });
    if (up && up.isValid() && (up.isAir || up.typeId === "minecraft:water")) {
      player.teleport(up);
      unstuck = true;
      break;
    }
    if (!onlyCheckUp) {
      let down = dim.getBlock({ x: source.x, y: source.y - iterations, z: source.z });
      if (down && down.isValid() && (down.isAir || down.typeId === "minecraft:water")) {
        player.teleport(down);
        unstuck = true;
        break;
      }
      let north = dim.getBlock({ x: source.x, y: source.y, z: source.z - iterations });
      if (north && north.isValid() && (north.isAir || north.typeId === "minecraft:water")) {
        player.teleport(north);
        unstuck = true;
        break;
      }
      let south = dim.getBlock({ x: source.x, y: source.y, z: source.z + iterations });
      if (south && south.isValid() && (south.isAir || south.typeId === "minecraft:water")) {
        player.teleport(south);
        unstuck = true;
        break;
      }
      let east = dim.getBlock({ x: source.x + iterations, y: source.y, z: source.z });
      if (east && east.isValid() && (east.isAir || east.typeId === "minecraft:water")) {
        player.teleport(east);
        unstuck = true;
        break;
      }
      let west = dim.getBlock({ x: source.x - iterations, y: source.y, z: source.z });
      if (west && west.isValid() && (west.isAir || west.typeId === "minecraft:water")) {
        player.teleport(west);
        unstuck = true;
        break;
      }
    }

    if (iterations >= 10000) return false;
  }
  return true;
}

export const GeomancyWhitelist = [
  "minecraft:coal_ore",
  "minecraft:copper_ore",
  "minecraft:diamond_ore",
  "minecraft:emerald_ore",
  "minecraft:gold_ore",
  "minecraft:iron_ore",
  "minecraft:lapis_ore",
  "minecraft:redstone_ore",
  "minecraft:lit_redstone_ore",
  "minecraft:deepslate_coal_ore",
  "minecraft:deepslate_copper_ore",
  "minecraft:deepslate_diamond_ore",
  "minecraft:deepslate_emerald_ore",
  "minecraft:deepslate_gold_ore",
  "minecraft:deepslate_iron_ore",
  "minecraft:deepslate_lapis_ore",
  "minecraft:deepslate_redstone_ore",
  "minecraft:lit_deepslate_redstone_ore",
  "minecraft:andesite_double_slab",
  "minecraft:andesite_slab",
  "minecraft:andesite_stairs",
  "minecraft:andesite_wall",
  "minecraft:andesite",
  "minecraft:andesite",
  "minecraft:basalt",
  "minecraft:blackstone",
  "minecraft:brick_slab",
  "minecraft:chiseled_deepslate_bricks",
  "minecraft:chiseled_deepslate",
  "minecraft:chiseled_polished_blackstone",
  "minecraft:chiseled_quartz_block",
  "minecraft:chiseled_tuff_bricks",
  "minecraft:chiseled_tuff",
  "minecraft:clay",
  "minecraft:coarse_dirt",
  "minecraft:cobbled_deepslate_double_slab",
  "minecraft:cobbled_deepslate_double_slab",
  "minecraft:cobbled_deepslate_slab",
  "minecraft:cobbled_deepslate_slab",
  "minecraft:cobbled_deepslate_stairs",
  "minecraft:cobbled_deepslate_stairs",
  "minecraft:cobbled_deepslate_wall",
  "minecraft:cobbled_deepslate_wall",
  "minecraft:cobbled_deepslate",
  "minecraft:cobbled_deepslate",
  "minecraft:cobblestone_double_slab",
  "minecraft:cobblestone_slab",
  "minecraft:cobblestone_slab",
  "minecraft:cobblestone_stairs",
  "minecraft:cobblestone_wall",
  "minecraft:cobblestone",
  "minecraft:cobblestone",
  "minecraft:cracked_deepslate_bricks",
  "minecraft:crying_obsidian",
  "minecraft:cut_red_sandstone_slab",
  "minecraft:cut_sandstone_slab",
  "minecraft:dark_prismarine_slab",
  "minecraft:dark_prismarine",
  "minecraft:deepslate_brick_double_slab",
  "minecraft:deepslate_brick_slab",
  "minecraft:deepslate_brick_stairs",
  "minecraft:deepslate_brick_wall",
  "minecraft:deepslate_bricks",
  "minecraft:deepslate_double_slab",
  "minecraft:deepslate_slab",
  "minecraft:deepslate_stairs",
  "minecraft:deepslate_tile_slab",
  "minecraft:deepslate_tiles",
  "minecraft:deepslate_wall",
  "minecraft:deepslate",
  "minecraft:diorite_double_slab",
  "minecraft:diorite_slab",
  "minecraft:diorite_stairs",
  "minecraft:diorite_wall",
  "minecraft:diorite",
  "minecraft:diorite",
  "minecraft:dirt_path",
  "minecraft:dirt_with_roots",
  "minecraft:dirt",
  "minecraft:dirt",
  "minecraft:dripstone_block",
  "minecraft:farmland",
  "minecraft:granite_double_slab",
  "minecraft:granite_slab",
  "minecraft:granite_stairs",
  "minecraft:granite_wall",
  "minecraft:granite",
  "minecraft:granite",
  "minecraft:gravel",
  "minecraft:grass_block",
  "minecraft:grass_block",
  "minecraft:grass_path",
  "minecraft:hardened_clay",
  "minecraft:magma_block",
  "minecraft:mossy_cobblestone_double_slab",
  "minecraft:mossy_cobblestone_slab",
  "minecraft:mossy_cobblestone_stairs",
  "minecraft:mossy_cobblestone_wall",
  "minecraft:mossy_cobblestone",
  "minecraft:mud_brick_slab",
  "minecraft:mycelium",
  "minecraft:nether_brick_fence",
  "minecraft:nether_brick_slab",
  "minecraft:nylium",
  "minecraft:podzol",
  "minecraft:polished_andesite_double_slab",
  "minecraft:polished_andesite_slab",
  "minecraft:polished_andesite_stairs",
  "minecraft:polished_andesite_wall",
  "minecraft:polished_andesite",
  "minecraft:polished_basalt",
  "minecraft:polished_blackstone_slab",
  "minecraft:polished_blackstone_stairs",
  "minecraft:polished_blackstone_wall",
  "minecraft:polished_deepslate_double_slab",
  "minecraft:polished_deepslate_slab",
  "minecraft:polished_deepslate_stairs",
  "minecraft:polished_deepslate_wall",
  "minecraft:polished_deepslate",
  "minecraft:polished_diorite_double_slab",
  "minecraft:polished_diorite_slab",
  "minecraft:polished_diorite_stairs",
  "minecraft:polished_diorite_wall",
  "minecraft:polished_diorite",
  "minecraft:polished_granite_double_slab",
  "minecraft:polished_granite_slab",
  "minecraft:polished_granite_stairs",
  "minecraft:polished_granite_wall",
  "minecraft:polished_granite",
  "minecraft:polished_tuff_double_slab",
  "minecraft:polished_tuff_slab",
  "minecraft:polished_tuff_stairs",
  "minecraft:polished_tuff_wall",
  "minecraft:polished_tuff",
  "minecraft:prismarine_brick_slab",
  "minecraft:prismarine_slab",
  "minecraft:prismarine",
  "minecraft:purpur_block",
  "minecraft:purpur_pillar",
  "minecraft:purpur_slab",
  "minecraft:quartz_block",
  "minecraft:quartz_pillar",
  "minecraft:quartz_slab",
  "minecraft:red_sand",
  "minecraft:red_sandstone_slab",
  "minecraft:red_sandstone",
  "minecraft:sand",
  "minecraft:sandstone_slab",
  "minecraft:sandstone",
  "minecraft:smooth_basalt",
  "minecraft:smooth_quartz",
  "minecraft:smooth_stone_slab",
  "minecraft:smooth_stone",
  "minecraft:soul_sand",
  "minecraft:soul_soil",
  "minecraft:stone_brick_slab",
  "minecraft:stone_slab",
  "minecraft:stone",
  "minecraft:suspicious_gravel",
  "minecraft:suspicious_sand",
  "minecraft:tuff_brick_double_slab",
  "minecraft:tuff_brick_slab",
  "minecraft:tuff_brick_stairs",
  "minecraft:tuff_brick_wall",
  "minecraft:tuff_bricks",
  "minecraft:tuff_double_slab",
  "minecraft:tuff_slab",
  "minecraft:tuff_stairs",
  "minecraft:tuff_wall",
  "minecraft:tuff",
  "minecraft:red_sand",
  "minecraft:red_sandstone",
  "minecraft:red_sandstone_slab",
  "minecraft:red_sandstone_double_slab",
  "minecraft:red_sandstone_wall",
  "minecraft:red_sandstone_stairs",
  "minecraft:cut_red_sandstone",
  "minecraft:cut_red_sandstone_slab",
  "minecraft:cut_red_sandstone_double_slab",
  "minecraft:smooth_red_sandstone",
  "minecraft:smooth_red_sandstone_slab",
  "minecraft:smooth_red_sandstone_double_slab",
  "minecraft:chiseled_red_sandstone",
  "minecraft:chiseled_red_sandstone_slab",
  "minecraft:chiseled_red_sandstone_double_slab",
  "hf_mzs:red_raked_sand",
  "minecraft:sand",
  "minecraft:sandstone",
  "minecraft:sandstone_slab",
  "minecraft:sandstone_double_slab",
  "minecraft:sandstone_wall",
  "minecraft:sandstone_stairs",
  "minecraft:suspicious_sand",
  "minecraft:cut_sandstone",
  "minecraft:cut_sandstone_slab",
  "minecraft:cut_sandstone_double_slab",
  "minecraft:smooth_sandstone",
  "minecraft:smooth_sandstone_slab",
  "minecraft:smooth_sandstone_double_slab",
  "minecraft:chiseled_sandstone",
  "minecraft:chiseled_sandstone_slab",
  "minecraft:chiseled_sandstone_double_slab",
  "hf_mzs:raked_sand",
  "minecraft:dirt",
  "minecraft:grass_block",
  "minecraft:grass_path",
  "minecraft:dirt_with_roots",
  "minecraft:coarse_dirt",
  "minecraft:farmland",
  "minecraft:myceium",
  "minecraft:podzol",
  "minecraft:mud",
];

const DirtTypes = [
  "minecraft:dirt",
  "minecraft:grass_block",
  "minecraft:grass_path",
  "minecraft:dirt_with_roots",
  "minecraft:coarse_dirt",
  "minecraft:farmland",
  "minecraft:myceium",
  "minecraft:podzol",
  "minecraft:mud",
];
const SandTypes = [
  "minecraft:sand",
  "minecraft:sandstone",
  "minecraft:sandstone_slab",
  "minecraft:sandstone_double_slab",
  "minecraft:sandstone_wall",
  "minecraft:sandstone_stairs",
  "minecraft:suspicious_sand",
  "minecraft:cut_sandstone",
  "minecraft:cut_sandstone_slab",
  "minecraft:cut_sandstone_double_slab",
  "minecraft:smooth_sandstone",
  "minecraft:smooth_sandstone_slab",
  "minecraft:smooth_sandstone_double_slab",
  "minecraft:chiseled_sandstone",
  "minecraft:chiseled_sandstone_slab",
  "minecraft:chiseled_sandstone_double_slab",
  "hf_mzs:raked_sand",
];
const RedSandTypes = [
  "minecraft:red_sand",
  "minecraft:red_sandstone",
  "minecraft:red_sandstone_slab",
  "minecraft:red_sandstone_double_slab",
  "minecraft:red_sandstone_wall",
  "minecraft:red_sandstone_stairs",
  "minecraft:cut_red_sandstone",
  "minecraft:cut_red_sandstone_slab",
  "minecraft:cut_red_sandstone_double_slab",
  "minecraft:smooth_red_sandstone",
  "minecraft:smooth_red_sandstone_slab",
  "minecraft:smooth_red_sandstone_double_slab",
  "minecraft:chiseled_red_sandstone",
  "minecraft:chiseled_red_sandstone_slab",
  "minecraft:chiseled_red_sandstone_double_slab",
  "hf_mzs:red_raked_sand",
];
const AndesiteTypes = [
  "minecraft:andesite",
  "minecraft:andesite_double_slab",
  "minecraft:andesite_slab",
  "minecraft:andesite_stairs",
  "minecraft:andesite_wall",
  "minecraft:polished_andesite",
  "minecraft:polished_andesite_double_slab",
  "minecraft:polished_andesite_slab",
  "minecraft:polished_andesite_stairs",
  "minecraft:polished_andesite_wall",
];
const GraniteTypes = [
  "minecraft:granite",
  "minecraft:granite_double_slab",
  "minecraft:granite_slab",
  "minecraft:granite_stairs",
  "minecraft:granite_wall",
  "minecraft:polished_granite",
  "minecraft:polished_granite_double_slab",
  "minecraft:polished_granite_slab",
  "minecraft:polished_granite_stairs",
  "minecraft:polished_granite_wall",
];
const DioriteTypes = [
  "minecraft:diorite",
  "minecraft:diorite_double_slab",
  "minecraft:diorite_slab",
  "minecraft:diorite_stairs",
  "minecraft:diorite_wall",
  "minecraft:polished_diorite",
  "minecraft:polished_diorite_double_slab",
  "minecraft:polished_diorite_slab",
  "minecraft:polished_diorite_stairs",
  "minecraft:polished_diorite_wall",
];
const TuffTypes = [
  "minecraft:tuff",
  "minecraft:tuff_double_slab",
  "minecraft:tuff_slab",
  "minecraft:tuff_stairs",
  "minecraft:tuff_wall",
  "minecraft:tuff_bricks",
  "minecraft:tuff_brick_double_slab",
  "minecraft:tuff_brick_slab",
  "minecraft:tuff_brick_stairs",
  "minecraft:tuff_brick_wall",
  "minecraft:chiseled_tuff",
  "minecraft:chiseled_tuff_bricks",
  "minecraft:polished_tuff",
  "minecraft:polished_tuff_double_slab",
  "minecraft:polished_tuff_slab",
  "minecraft:polished_tuff_stairs",
  "minecraft:polished_tuff_wall",
];
const DeepslateTypes = [
  "minecraft:deepslate",
  "minecraft:infested_deepslate",
  "minecraft:deepslate_double_slab",
  "minecraft:deepslate_slab",
  "minecraft:deepslate_stairs",
  "minecraft:deepslate_wall",
  "minecraft:cobbled_deepslate",
  "minecraft:cobbled_deepslate_double_slab",
  "minecraft:cobbled_deepslate_slab",
  "minecraft:cobbled_deepslate_stairs",
  "minecraft:cobbled_deepslate_wall",
  "minecraft:deepslate_bricks",
  "minecraft:deepslate_brick_double_slab",
  "minecraft:deepslate_brick_slab",
  "minecraft:deepslate_brick_stairs",
  "minecraft:deepslate_brick_wall",
  "minecraft:chiseled_deepslate",
  "minecraft:chiseled_deepslate_bricks",
  "minecraft:polished_deepslate",
  "minecraft:polished_deepslate_double_slab",
  "minecraft:polished_deepslate_slab",
  "minecraft:polished_deepslate_stairs",
  "minecraft:polished_deepslate_wall",
];
const CobbledDeepslateTypes = [
  "minecraft:cobbled_deepslate",
  "minecraft:cobbled_deepslate_double_slab",
  "minecraft:cobbled_deepslate_slab",
  "minecraft:cobbled_deepslate_stairs",
  "minecraft:cobbled_deepslate_wall",
];
const CobblestoneTypes = [
  "minecraft:cobblestone",
  "minecraft:infested_cobblestone",
  "minecraft:cobblestone_double_slab",
  "minecraft:cobblestone_slab",
  "minecraft:cobblestone_stairs",
  "minecraft:cobblestone_wall",
  "minecraft:mossy_cobblestone",
  "minecraft:mossy_cobblestone_double_slab",
  "minecraft:mossy_cobblestone_slab",
  "minecraft:mossy_cobblestone_stairs",
  "minecraft:mossy_cobblestone_wall",
];

const PassableBlocks = [
  "minecraft:grass",
  "minecraft:short_grass",
  "minecraft:tall_grass",
  "minecraft:seagrass",
  "minecraft:cornflower",
  "minecraft:sunflower",
  "minecraft:torchflower",
  "minecraft:torchflower_crop",
  "minecraft:standing_banner",
  "minecraft:wall_banner",
  "minecraft:acacia_button",
  "minecraft:bamboo_button",
  "minecraft:birch_button",
  "minecraft:cherry_button",
  "minecraft:crimson_button",
  "minecraft:dark_oak_button",
  "minecraft:jungle_button",
  "minecraft:mangrove_button",
  "minecraft:polished_blackstone_button",
  "minecraft:spruce_button",
  "minecraft:stone_button",
  "minecraft:warped_button",
  "minecraft:wooden_button",
  "minecraft:carrots",
  "minecraft:brain_coral_fan",
  "minecraft:bubble_coral_fan",
  "minecraft:dead_brain_coral_fan",
  "minecraft:dead_bubble_coral_fan",
  "minecraft:dead_fire_coral_fan",
  "minecraft:dead_horn_coral_fan",
  "minecraft:dead_tube_coral_fan",
  "minecraft:fire_coral_fan",
  "minecraft:horn_coral_fan",
  "minecraft:tube_coral_fan",
  "minecraft:deadbush",
  "minecraft:fire",
  "minecraft:crimson_fungus",
  "minecraft:warped_fungus",
  "minecraft:glow_frame",
  "minecraft:frame",
  "minecraft:glow_lichen",
  "minecraft:sweet_berry_bush",
  "minecraft:cave_vines_body_with_berries",
  "minecraft:cave_vines_head_with_berries",
  "minecraft:crimson_root",
  "minecraft:warped_root",
  "minecraft:hanging_root",
  "minecraft:kelp",
  "minecraft:lever",
  "minecraft:light_block_0",
  "minecraft:light_block_1",
  "minecraft:light_block_2",
  "minecraft:light_block_3",
  "minecraft:light_block_4",
  "minecraft:light_block_5",
  "minecraft:light_block_6",
  "minecraft:light_block_7",
  "minecraft:light_block_8",
  "minecraft:light_block_9",
  "minecraft:light_block_10",
  "minecraft:light_block_11",
  "minecraft:light_block_12",
  "minecraft:light_block_13",
  "minecraft:light_block_14",
  "minecraft:light_block_15",
  "minecraft:mangrove_propagule",
  "minecraft:melon_stem",
  "minecraft:brown_mushroom",
  "minecraft:red_mushroom",
  "minecraft:nether_wart",
  "minecraft:pink_petals",
  "minecraft:pitcher_crop",
  "minecraft:pitcher_plant",
  "minecraft:potatoes",
  "minecraft:pumpkin_stem",
  "minecraft:acacia_sapling",
  "minecraft:bamboo_sapling",
  "minecraft:birch_sapling",
  "minecraft:cherry_sapling",
  "minecraft:dark_oak_sapling",
  "minecraft:jungle_sapling",
  "minecraft:oak_sapling",
  "minecraft:spruce_sapling",
  "minecraft:sculk_vein",
  "minecraft:spore_blossom",
  "minecraft:trip_wire",
  "minecraft:structure_void",
  "minecraft:reeds",
  "minecraft:vines",
  "minecraft:cave_vines",
  "minecraft:twisting_vines",
  "minecraft:weeping_vines",
  "minecraft:wheat",
  "minecraft:beetroot",
  "minecraft:yellow_flower",
  "minecraft:red_flower",
  "minecraft:double_plant",
  "minecraft:wither_rose",
];
