import { world, system, Player, Entity, BlockPermutation, ItemStack, BlockTypes, Block } from "@minecraft/server";
import showDialogueOnItemUse from "./util/show-dialogue-on-item-use";
import growTreeFruit from "./trees/growTreefruit";
import growTreeSmall from "./trees/growTreesmall";
import growTreeMedium from "./trees/growTreemedium";
import growTreeLarge from "./trees/growTreelarge";
import growTreeRedwood from "./trees/growTreeredwood";
import chainsawtree from "./tools/chainsawtree";
import fruitshaker from "./tools/fruitshaker";
import juiceFruit from "./machines/juicefruit";
import slushJuice from "./machines/slushjuice";
import boilFruit from "./machines/boilfruit";
import createJam from "./machines/createjam";
import createJuice from "./machines/createjuice";
import createSlushie from "./machines/createslushie";
import chopFruit from "./machines/chopfruit";
import slicepie from "./blocks/slicepie";
import stripLog from "./tools/striplog";
import shearLeaf from "./tools/shearleaf";
import bonemealSapling from "./trees/bonemealSapling";
import removejam from "./blocks/removejam";
import showsettings from "./util/showsettings";
import showfirsttime from "./util/showfirsttime";
import growTree9_11_13 from "./trees/growTree9_11_13";
import growTree9_9_11_13 from "./trees/growTree9_11_13";
import growTreeBone from "./trees/growTreeBone";
import growTree15_17_19 from "./trees/growTree15_17_19";
import growTreeMushroom from "./trees/growTreeMushroom";
import growTreePine from "./trees/growTreePine";
import growTreeGiantCherry from "./trees/growGiantCherry";
import growTreeCoconut from "./trees/growTreeCoconut";
import growTreeAvocado from "./trees/growTreeAvocado";
import growTreePinkOleander from "./trees/growTreePinkOleander";
import checkTreeGrowSpace from "./trees/checkTreeGrowSpace";

import {
  forestryLogs,
  forestryLeaves,
  forestryLeavesPlusVanilla,
  forestryFruit,
  forestryFruitPlusSap,
  forestryFruitItems,
  forestryChoppedFruitItems,
  forestryPies,
  forestryJuice,
  strippingTools,
  vanillaLogs,
  fruitSaplings,
  mediumSaplings,
  largeSaplings,
  redwooodSaplings,
  smallSaplings,
  allSaplings,
  shearTools,
  forestryLogsPlusVanilla,
  JamJars,
  JamItems,
  ForestrySlabs,
  doorTypes,
  gateTypes,
  treeTemps,
  saplingspawnallowedblocks,
  fenceinv,
  fenceTypes,
  stairTypes,
  fenceexcludeBlocksArray,
  treeTempsArray,
  forestryChoppedFruitItemsNoSap,
  forestryFruitPlusSapPlusTemps,
  sapling_9_11_13,
  sapling_9_9_11_13,
  bonesapling,
  mushroomsapling,
  pinesapling,
  sapling_15_17_19,
  vanilla_cherry,
  coconutsapling,
  avocadoSaplings,
  pinkOleanderSaplings,
} from "./globals";

let ow = world.getDimension("overworld");
const EVENT_ID = "float_fc:showtranslateui";
const SETTINGS_EVENT_ID = "float_fc:showsettings";
const FIRSTTIME_EVENT_ID = "float_fc:firsttime";
world.afterEvents.playerSpawn.subscribe((event) => {
  try {
    if (event.player) {
      if (event.player.hasTag("has_float_fc_book")) {
      } else {
        event.player.runCommandAsync("function fs/f/init");
      }
    }
  } catch {}
});

//LEAF DECAY CONTROLLERS
/*
world.beforeEvents.worldInitialize.subscribe((eventData) => {
  eventData.blockComponentRegistry.registerCustomComponent("float_fc:on_random_tick", {
    onRandomTick(e) {
      const { block } = e;
      const { x, y, z } = block.location;
      const persistent = isConnectedToAllowedBlock(block, 5);
      const currentStates = block.permutation.getAllStates();
      const newStates = { ...currentStates, "float_fc:persistent": persistent };
      const newPermutation = BlockPermutation.resolve(block.typeId, newStates);
      block.setPermutation(newPermutation);

      if (!persistent && !block.permutation.getState("float_fc:placed")) {
        block.dimension.runCommand(`/setblock ${x} ${y} ${z} air destroy`);
      }
    },
  });
});
*/

/*
function isConnectedToAllowedBlock(block, maxDistance) {
  const queue = [{ block, dist: 0 }];
  const visited = new Set();
  let processedCount = 0; // To track how many blocks were processed

  while (queue.length > 0) {
    const { block: currentBlock, dist } = queue.shift();

    // Skip this block if we've exceeded max distance
    if (dist > maxDistance) {
      console.error(
        `Skipped block at ${currentBlock.location.x}, ${currentBlock.location.y}, ${currentBlock.location.z} - Distance exceeded`
      );
      continue;
    }

    const { x, y, z } = currentBlock.location;
    const blockKey = `${x},${y},${z}`;

    // If the block has already been visited at this distance or shorter, skip it
    if (visited.has(blockKey)) {
      console.error(`Skipped block at ${x}, ${y}, ${z} - Already visited`);
      continue;
    }

    // Mark the block as visited
    visited.add(blockKey);
    console.error(`Processing block at ${x}, ${y}, ${z} with dist ${dist}`);

    processedCount++; // Count each processed block

    // If the block is a forestry log, return true
    if (forestryLogs.has(currentBlock.typeId)) {
      console.error(`Forestry log found at ${x}, ${y}, ${z} - Returning true`);
      return true;
    }

    // If the block is a forestry leaf
    if (currentBlock.typeId === "float_fc:baobab_leaves") {
      const persistentBit = currentBlock.permutation?.getState("float_fc:persistent");

      if (persistentBit === true || dist === 0) {
        const adjacentBlocks = [
          currentBlock.above(),
          currentBlock.below(),
          currentBlock.north(),
          currentBlock.south(),
          currentBlock.east(),
          currentBlock.west(),
          // Diagonal blocks (horizontal)
          currentBlock.north().east(),
          currentBlock.north().west(),
          currentBlock.south().east(),
          currentBlock.south().west(),

          // Diagonal blocks (vertical)
          currentBlock.above().north(),
          currentBlock.above().south(),
          currentBlock.above().east(),
          currentBlock.above().west(),
          currentBlock.below().north(),
          currentBlock.below().south(),
          currentBlock.below().east(),
          currentBlock.below().west(),

          // Diagonal blocks in 3D (both horizontal and vertical)
          currentBlock.above().north().east(),
          currentBlock.above().north().west(),
          currentBlock.above().south().east(),
          currentBlock.above().south().west(),
          currentBlock.below().north().east(),
          currentBlock.below().north().west(),
          currentBlock.below().south().east(),
          currentBlock.below().south().west(),
        ];

        console.error(`Found ${adjacentBlocks.length} adjacent blocks to process at ${x}, ${y}, ${z}`);

        // Push adjacent blocks to the queue if they haven't been visited
        for (const adjacentBlock of adjacentBlocks) {
          if (adjacentBlock != null) {
            const adjX = adjacentBlock.location.x;
            const adjY = adjacentBlock.location.y;
            const adjZ = adjacentBlock.location.z;
            const adjacentKey = `${adjX},${adjY},${adjZ}`;

            if (!adjacentBlock.isValid()) {
              console.error(`Invalid adjacent block at ${adjX}, ${adjY}, ${adjZ}`);
            } else if (visited.has(adjacentKey)) {
              console.error(`Already visited adjacent block at ${adjX}, ${adjY}, ${adjZ}`);
            } else {
              console.error(`Queueing adjacent block at ${adjX}, ${adjY}, ${adjZ} with dist ${dist + 1}`);
              queue.push({ block: adjacentBlock, dist: dist + 1 });
            }
          } else {
            console.error(`Null adjacent block found at ${x}, ${y}, ${z}`);
          }
        }
      } else {
        console.error(`Persistent bit is false and distance is greater than 0 at ${x}, ${y}, ${z}`);
      }
    }
  }

  // If the loop finishes processing and no valid block is found
  console.error(`All blocks processed (${processedCount}), max distance reached, returning false`);
  return false;
}

world.afterEvents.playerPlaceBlock.subscribe((eventData) => {
  const { block } = eventData;
  if (forestryLeaves.has(block.typeId) && !block.permutation.getState("float_fc:placed")) {
    const currentStates = block.permutation.getAllStates();
    const newStates = { ...currentStates, "float_fc:placed": true };
    const newPermutation = BlockPermutation.resolve(block.typeId, newStates);
    block.setPermutation(newPermutation);
  }
});
*/

// Constants for controlling update intervals and search areas
const playerUpdateInterval = 140; // Time interval to check for players
const airCheckRadius = 8; // Radius for air block checks
const airCheckRadiusSquared = 64; // Square of air check radius (8^2)
const searchRadius = 25; // Radius for entity search
const searchRadiusbase = 100; // Base search radius for specific entities

// Variables to store game state and entity/player references
var playerResponse, lastResponseAt, player, players, nearbybaseprotector, tempBlock, nearbyEntities, x0, y0, z0, dx, dz;
var playerIndex,
  typeIndex = 0; // Index variables for loops
var cancelEntity = false; // Flag to determine if the entity spawning should be canceled

// Function to handle tree spawning cancelling
function treeSpawn(event) {
  try {
    if (event.entity != undefined) {
      if (treeTemps.has(event.entity.typeId)) {
        // Throttle the player update check based on a time interval
        if (lastResponseAt == undefined || Date.now() - lastResponseAt > playerUpdateInterval) {
          // Get all players in the world
          players = world.getPlayers();

          // Loop through players and check if any has the "no_tree_spawn" tag
          for (playerIndex = 0; playerIndex < players.length && !cancelEntity; playerIndex++) {
            player = players[playerIndex];
            if (player != undefined) {
              // Set cancelEntity to true if any player has the tag
              cancelEntity = cancelEntity || world.getDynamicProperty("no_tree_spawning");
            }
          }
          // Reset player variables and store response
          player = players = undefined;
          playerResponse = cancelEntity;
          lastResponseAt = Date.now();
        } else {
          // Use cached response if update interval hasn't passed
          cancelEntity = playerResponse;
        }

        // Check for nearby base protectors
        if (!cancelEntity) {
          try {
            nearbybaseprotector = event.entity.dimension.getEntities({
              location: event.entity.location,
              maxDistance: searchRadiusbase,
              type: "float_fc:base_protector",
            });
            cancelEntity = nearbybaseprotector.length > 0;
            nearbybaseprotector = undefined;
          } catch (e) {}
        }

        // Check if any trees are nearby
        if (!cancelEntity) {
          // Loop through possible tree types
          for (typeIndex = 0; typeIndex < treeTempsArray.length && !cancelEntity; typeIndex++) {
            nearbyEntities = event.entity.dimension.getEntities({
              location: event.entity.location,
              maxDistance: searchRadius,
              type: treeTempsArray[typeIndex],
            });
            // Cancel entity if any trees are nearby
            cancelEntity = nearbyEntities.length > 1;
          }
          nearbyEntities = undefined;
        }

        // Final check: ensure the area has enough air blocks for the tree to spawn
        if (!cancelEntity) {
          x0 = Math.floor(event.entity.location.x); // X-coordinate of the entity
          y0 = Math.floor(event.entity.location.y) + 4; // Offset in the Y-axis for checking above spawn point
          z0 = Math.floor(event.entity.location.z); // Z-coordinate of the entity

          // Loop through an area defined by the air check radius
          for (dx = -airCheckRadius; dx <= airCheckRadius && !cancelEntity; dx++) {
            for (dz = -airCheckRadius; dz <= airCheckRadius && !cancelEntity; dz++) {
              // Check within a circle defined by the radius
              if (dx * dx + dz * dz <= airCheckRadiusSquared) {
                tempBlock = event.entity.dimension.getBlock({ x: x0 + dx, y: y0, z: z0 + dz });
                // Cancel if the block is not air or not in the allowed blocks for sapling spawn
                cancelEntity =
                  !tempBlock ||
                  (tempBlock.typeId !== "minecraft:air" && !saplingspawnallowedblocks.has(tempBlock.typeId));
              }
            }
          }
          tempBlock = undefined;
        }

        // If any condition was met to cancel, trigger the entity's kill event
        try {
          if (cancelEntity) {
            event.entity.triggerEvent("float_fc:kill_entity");
          } else {
            checkForSapling(event);
          }
        } catch (error) {}
      }
    }
    cancelEntity = false; // Reset the cancel flag for the next entity spawn event
  } catch (error) {}
}

// Subscribe the treeSpawn function to the entity spawn event
world.afterEvents.entitySpawn.subscribe(treeSpawn);

function directionDisplay(angle) {
  if (Math.abs(angle) > 112.5) return "north";
  if (Math.abs(angle) < 67.5) return "south";
  if (angle < 157.5 && angle > 22.5) return "west";
  if (angle > -157.5 && angle < -22.5) return "east";
  return "east";
}

const processedBlocks = new Map();
var selectedItem,
  equipment,
  slabItem,
  targetBlock,
  aboveBlock,
  northBlock,
  southBlock,
  eastBlock,
  westBlock,
  newPermutation,
  currentStates,
  cardinalDirection,
  blockAbove,
  aboveBlock,
  blockStates,
  blockAboveStates,
  aboveBlockCardinalDirection = undefined;
var newOpenState = false;
world.beforeEvents.worldInitialize.subscribe((event) => {
  event.blockComponentRegistry.registerCustomComponent("float_fc:step_on_palisade", {
    onStepOn(e) {
      const currentStates = e.block.permutation.getAllStates();
      const isSheared = currentStates["float_fc:sheared"];
      const entity = e.entity;
      if (entity && isSheared) {
        entity.applyDamage(1); // Apply 1 damage
      }
    },
  });
  event.blockComponentRegistry.registerCustomComponent("float_fc:fall_on_palisade", {
    onEntityFallOn(e) {
      const entity = e.entity;
      const currentStates = e.block.permutation.getAllStates();
      const isSheared = currentStates["float_fc:sheared"];
      if (entity && entity.fallDistance && isSheared) {
        entity.applyDamage(Math.ceil(entity.fallDistance)); // Apply damage based on fall distance
      }
    },
  });
  event.blockComponentRegistry.registerCustomComponent("float_fc:on_tick_palisade", {
    onTick(e) {
      const currentStates = e.block.permutation.getAllStates();
      const isSheared = currentStates["float_fc:sheared"];
      const isBottom = currentStates["float_fc:bottom"];
      const direction = currentStates["minecraft:cardinal_direction"];
      if (!isSheared || !isBottom) {
        return;
      } else {
        let frontLocation;
        switch (direction) {
          case "south": // South
            frontLocation = { x: e.block.location.x, y: e.block.location.y, z: e.block.location.z + 1 };
            break;
          case "west": // West
            frontLocation = { x: e.block.location.x - 1, y: e.block.location.y, z: e.block.location.z };
            break;
          case "north": // North
            frontLocation = { x: e.block.location.x, y: e.block.location.y, z: e.block.location.z - 1 };
            break;
          case "east": // East
            frontLocation = { x: e.block.location.x + 1, y: e.block.location.y, z: e.block.location.z };
            break;
          default:
            return;
        }
        if (frontLocation) {
          const frontBlock = e.block.dimension.getBlock(frontLocation);
          if (frontBlock && frontBlock.typeId === "minecraft:air") {
            const entitiesAtFront = e.block.dimension.getEntities({
              location: frontLocation,
              maxDistance: 1,
            });

            for (const entity of entitiesAtFront) {
              entity.applyDamage(2); // Apply 2 damage
              const rotation = entity.getRotation(); // Get the entity's rotation
              const knockbackDirection = {
                x: -Math.sin(rotation.y * (Math.PI / 180)), // Calculate knockback based on entity's yaw rotation
                y: 0,
                z: -Math.cos(rotation.y * (Math.PI / 180)),
              };

              // Apply a small knockback effect
              entity.applyKnockback(knockbackDirection.x, 0.1, knockbackDirection.z, 0.5);
            }
          } else {
            return;
          }
        }
      }
    },
  });
  // Set entity on fire when stepping on the block
  event.blockComponentRegistry.registerCustomComponent("float_fc:on_step_flames", {
    onStepOn(e) {
      const entity = e.entity;
      if (entity) {
        entity.setOnFire(3); // Set entity on fire for 3 seconds
      }
    },
    onEntityFallOn(e) {
      const entity = e.entity;
      if (entity) {
        entity.setOnFire(3); // Set entity on fire for 3 seconds
      }
    },
  });

  //Trapdoor Interact
  event.blockComponentRegistry.registerCustomComponent("float_fc:on_interact_trap", {
    onPlayerInteract(e) {
      try {
        newPermutation = BlockPermutation.resolve(e.block.typeId, {
          ...e.block.permutation.getAllStates(),
          "float_fc:open": !e.block.permutation.getState("float_fc:open"),
        });
        e.block.setPermutation(newPermutation);
        e.player.playSound(
          e.block.permutation.getState("float_fc:open") ? "open.wooden_trapdoor" : "close.wooden_trapdoor"
        );
      } catch (e) {}
      newPermutation = undefined;
    },
  });

  //Arrow Interact
  event.blockComponentRegistry.registerCustomComponent("float_fc:on_interact_arrow", {
    onPlayerInteract(e) {
      try {
        const currentStates = e.block.permutation.getAllStates();
        const currentDirection = currentStates["float_fc:direction"] || 0;

        // Calculate the next direction (cycling through 0, 1, 2, 3)
        // 0 = right, 1 = up, 2 = left, 3 = down
        const nextDirection = (currentDirection + 1) % 4;

        // Create new permutation with updated direction
        const newPermutation = BlockPermutation.resolve(e.block.typeId, {
          ...currentStates,
          "float_fc:direction": nextDirection,
        });

        // Apply the new permutation
        e.block.setPermutation(newPermutation);

        // Play appropriate sound
        e.player.playSound("dig.wood");
      } catch (err) {
        console.error("Error in arrow interaction:", err);
      }
    },
  });

  //Door Place
  event.blockComponentRegistry.registerCustomComponent("float_fc:on_place", {
    onPlace(e) {
      try {
        aboveBlock = e.block.above();
        northBlock = e.block.north();
        southBlock = e.block.south();
        eastBlock = e.block.east();
        westBlock = e.block.west();
        if (!processedBlocks.has(`${e.block.location.x},${e.block.location.y},${e.block.location.z}`)) {
          currentStates = e.block.permutation.getAllStates();
          cardinalDirection = currentStates["minecraft:cardinal_direction"];
          if (aboveBlock.typeId === "minecraft:air" && !e.block.permutation.getState("float_fc:upper_block_bit")) {
            newPermutation = BlockPermutation.resolve(e.block.typeId, {
              "float_fc:upper_block_bit": true,
              "minecraft:cardinal_direction": cardinalDirection, // Get all players in the world
            });
            aboveBlock.setPermutation(newPermutation);
            newPermutation = BlockPermutation.resolve(e.block.typeId, currentStates);
            e.block.setPermutation(newPermutation);
          }
          // Check neighboring blocks based on cardinal direction and door types set
          if (cardinalDirection == "south" && doorTypes.has(eastBlock?.typeId)) {
            blockStates = eastBlock.permutation.getAllStates();
            if (!blockStates["float_fc:door_hinge_bit"]) {
              newPermutation = BlockPermutation.resolve(e.block.typeId, {
                ...blockStates,
                "float_fc:door_hinge_bit": true,
              });
              e.block.setPermutation(newPermutation);
            }
            aboveBlockCardinalDirection = aboveBlock.permutation.getState("minecraft:cardinal_direction");
            blockAbove = aboveBlock.east();
            if (aboveBlockCardinalDirection === "south" && doorTypes.has(blockAbove?.typeId)) {
              blockAboveStates = blockAbove.permutation.getAllStates();
              if (!blockAboveStates["float_fc:door_hinge_bit"]) {
                newPermutation = BlockPermutation.resolve(aboveBlock.typeId, {
                  ...blockAboveStates,
                  "float_fc:door_hinge_bit": true,
                });
                aboveBlock.setPermutation(newPermutation);
              }
              blockAboveStates = undefined;
            }
          } else if (cardinalDirection == "east" && doorTypes.has(northBlock?.typeId)) {
            blockStates = northBlock.permutation.getAllStates();
            if (!blockStates["float_fc:door_hinge_bit"]) {
              newPermutation = BlockPermutation.resolve(e.block.typeId, {
                ...blockStates,
                "float_fc:door_hinge_bit": true,
              });
              e.block.setPermutation(newPermutation);
            }
            aboveBlockCardinalDirection = aboveBlock.permutation.getState("minecraft:cardinal_direction");
            blockAbove = aboveBlock.north();
            if (aboveBlockCardinalDirection === "east" && doorTypes.has(blockAbove?.typeId)) {
              blockAboveStates = blockAbove.permutation.getAllStates();
              if (!blockAboveStates["float_fc:door_hinge_bit"]) {
                newPermutation = BlockPermutation.resolve(aboveBlock.typeId, {
                  ...blockAboveStates,
                  "float_fc:door_hinge_bit": true,
                });
                aboveBlock.setPermutation(newPermutation);
              }
              blockAboveStates = undefined;
            }
          } else if (cardinalDirection == "north" && doorTypes.has(westBlock?.typeId)) {
            blockStates = westBlock.permutation.getAllStates();
            if (!blockStates["float_fc:door_hinge_bit"]) {
              newPermutation = BlockPermutation.resolve(e.block.typeId, {
                ...blockStates,
                "float_fc:door_hinge_bit": true,
              });
              e.block.setPermutation(newPermutation);
            }
            aboveBlockCardinalDirection = aboveBlock.permutation.getState("minecraft:cardinal_direction");
            blockAbove = aboveBlock.west();
            if (aboveBlockCardinalDirection === "north" && doorTypes.has(blockAbove?.typeId)) {
              blockAboveStates = blockAbove.permutation.getAllStates();
              if (!blockAboveStates["float_fc:door_hinge_bit"]) {
                newPermutation = BlockPermutation.resolve(aboveBlock.typeId, {
                  ...blockAboveStates,
                  "float_fc:door_hinge_bit": true,
                });
                aboveBlock.setPermutation(newPermutation);
              }
              blockAboveStates = undefined;
            }
          } else if (cardinalDirection == "west" && doorTypes.has(southBlock?.typeId)) {
            blockStates = southBlock.permutation.getAllStates();
            if (!blockStates["float_fc:door_hinge_bit"]) {
              newPermutation = BlockPermutation.resolve(e.block.typeId, {
                ...blockStates,
                "float_fc:door_hinge_bit": true,
              });
              e.block.setPermutation(newPermutation);
            }
            aboveBlockCardinalDirection = aboveBlock.permutation.getState("minecraft:cardinal_direction");
            blockAbove = aboveBlock.south();
            if (aboveBlockCardinalDirection === "west" && doorTypes.has(blockAbove?.typeId)) {
              blockAboveStates = blockAbove.permutation.getAllStates();
              if (!blockAboveStates["float_fc:door_hinge_bit"]) {
                newPermutation = BlockPermutation.resolve(aboveBlock.typeId, {
                  ...blockAboveStates,
                  "float_fc:door_hinge_bit": true,
                });
                aboveBlock.setPermutation(newPermutation);
              }
            }
          }
          processedBlocks.set(`${e.block.location.x},${e.block.location.y},${e.block.location.z}`, true);
        }
      } catch (e) {}
      aboveBlock =
        northBlock =
        southBlock =
        eastBlock =
        westBlock =
        currentStates =
        cardinalDirection =
        newPermutation =
        aboveBlockCardinalDirection =
        blockAbove =
        blockAboveStates =
          undefined;
    },
  });
  //Door Interact
  event.blockComponentRegistry.registerCustomComponent("float_fc:on_interact_door", {
    onPlayerInteract(e) {
      try {
        targetBlock = e.block.permutation.getState("float_fc:upper_block_bit") ? e.block.below() : e.block.above();
        e.block.setPermutation(
          BlockPermutation.resolve(e.block.typeId, {
            ...e.block.permutation.getAllStates(),
            "float_fc:open_bit": !e.block.permutation.getState("float_fc:open_bit"),
          })
        );
        targetBlock.setPermutation(
          BlockPermutation.resolve(targetBlock.typeId, {
            ...targetBlock.permutation.getAllStates(),
            "float_fc:open_bit": !targetBlock.permutation.getState("float_fc:open_bit"),
          })
        );
        e.player.playSound(
          e.block.permutation.getState("float_fc:open_bit") ? "close.wooden_door" : "open.wooden_door"
        );
      } catch (e) {}
      targetBlock = undefined;
    },
  });
  // stair placement
  event.blockComponentRegistry.registerCustomComponent("float_fc:stair_placement", {
    onPlace: (e) => {
      stairCheck(e?.block);
    },
    onPlayerDestroy: (e) => {
      stairCheck(e?.block);
    },
  });
  // Quarter placement
  event.blockComponentRegistry.registerCustomComponent("float_fc:on_interact_quarter", {
    onPlayerInteract: (e) => {
      const equipment = e.player.getComponent("equippable");
      const selectedItem = equipment?.getEquipment("Mainhand");
      const onplace = false;

      if (selectedItem?.typeId === e.block.typeId) {
        //console.error("Block type ID: " + e.block.typeId, "Facelocation: " + e.faceLocation.x);
        quarterPlace(e.block, e.faceLocation, e.face, onplace, e.player);

        // Remove 1 item from the player's main hand if not in creative mode
        if (e.player.getGameMode() !== "creative") {
          if (selectedItem.amount > 1) {
            selectedItem.amount -= 1;
            equipment.setEquipment("Mainhand", selectedItem);
          } else {
            equipment.setEquipment("Mainhand", undefined);
          }
        }

        // Play a place wood sound
        e.player.playSound("place.cherry_wood");
      }
    },
  });
  event.blockComponentRegistry.registerCustomComponent("float_fc:on_place_quarter", {
    beforeOnPlayerPlace: (e) => {
      const player = e.player;
      const onplace = true;
      const viewDirection = player.getViewDirection();
      const startPosition = player.getHeadLocation();
      const rayLength = 10; // Adjust the ray length as needed
      const rayDirection = {
        x: viewDirection.x,
        y: viewDirection.y,
        z: viewDirection.z,
      };

      const rayOptions = {
        maxDistance: rayLength,
        includeLiquidBlocks: false,
        includePassableBlocks: true,
      };

      const blockHit = player.dimension.getBlockFromRay(startPosition, rayDirection, rayOptions);
      if (blockHit) {
        const faceLocation = blockHit.faceLocation;
        const blockLocation = blockHit.block.location;
        const combinedLocation = {
          x: blockLocation.x + faceLocation.x,
          y: blockLocation.y + faceLocation.y,
          z: blockLocation.z + faceLocation.z,
        };

        //console.error(`Combined Location: x=${combinedLocation.x}, y=${combinedLocation.y}, z=${combinedLocation.z}`);
        const equipment = e.player.getComponent("equippable");
        const selectedItem = equipment?.getEquipment("Mainhand");
        storeCardinalDirectionOnPlace(e.block, player);

        quarterPlace(e.block, combinedLocation, e.face, onplace, player, e.permutationToPlace);
        system.run(() => {
          e.player.playSound("place.cherry_wood");
        });
        e.cancel = true; // Prevent the default placement behavior
      } else {
        console.log("No block was hit by the ray.");
      }
    },
  });
  // Path placement
  event.blockComponentRegistry.registerCustomComponent("float_fc:on_place_path", {
    onPlace: (e) => {
      pathCheck(e?.block);
    },
  });
  event.blockComponentRegistry.registerCustomComponent("float_fc:on_destroy_path", {
    onPlayerDestroy: (e) => {
      pathCheck(e?.block);
    },
  });
  //Palisade Placement
  event.blockComponentRegistry.registerCustomComponent("float_fc:on_place_palisade", {
    onPlace: (e) => {
      palisadeCheck(e?.block);
    },
  });
  event.blockComponentRegistry.registerCustomComponent("float_fc:on_destroy_palisade", {
    onPlayerDestroy: (e) => {
      palisadeCheck(e?.block);
    },
  });
  event.blockComponentRegistry.registerCustomComponent("float_fc:on_interact_palisade", {
    onPlayerInteract: (e) => {
      const equipment = e.player.getComponent("equippable");
      const selectedItem = equipment?.getEquipment("Mainhand");

      if (selectedItem && strippingTools.has(selectedItem.typeId)) {
        palisadeShear(e.block, e.player);
      } else {
        let targetLocation = { ...e.block.location };

        // Determine the target location based on the interaction face
        switch (e.face) {
          case "Up":
            targetLocation.y += 1;
            break;
          case "Down":
            targetLocation.y -= 1;
            break;
          case "North":
            targetLocation.z -= 1;
            break;
          case "South":
            targetLocation.z += 1;
            break;
          case "East":
            targetLocation.x += 1;
            break;
          case "West":
            targetLocation.x -= 1;
            break;
        }

        const targetBlock = e.block.dimension.getBlock(targetLocation);
        if (targetBlock.typeId === "minecraft:air") {
          if (selectedItem && BlockTypes.get(selectedItem.typeId)) {
            let cardinalDirection = e.block.permutation.getState("minecraft:cardinal_direction");

            // Ensure the placed block matches the direction of the existing palisade block
            if (!cardinalDirection) {
              // Fallback to player's rotation if cardinal direction is not available
              const playerRotation = e.player.getRotation().y;
              const face = e.face;

              if (face === "North" || (face === "Up" && playerRotation > 135 && playerRotation <= 225)) {
                cardinalDirection = "north";
              } else if (face === "South" || (face === "Up" && playerRotation > -45 && playerRotation <= 45)) {
                cardinalDirection = "south";
              } else if (face === "West" || (face === "Up" && playerRotation > 45 && playerRotation <= 135)) {
                cardinalDirection = "west";
              } else {
                cardinalDirection = "east";
              }
            }

            let placed = false;

            // Attempt to place the block with cardinal direction
            try {
              const newPermutation = BlockPermutation.resolve(selectedItem.typeId, {
                "minecraft:cardinal_direction": cardinalDirection,
              });
              targetBlock.setPermutation(newPermutation);
              e.player.playSound("use.wood");
              placed = true;
            } catch (error) {}

            // If placement with cardinal direction fails, place without it
            if (!placed) {
              targetBlock.setType(selectedItem.typeId);
              e.player.playSound("use.wood");
            }

            // Reduce the item count if the player is not in creative mode
            if (e.player.getGameMode() !== "creative") {
              if (selectedItem.amount > 1) {
                selectedItem.amount -= 1;
                equipment.setEquipment("Mainhand", selectedItem);
              } else {
                equipment.setEquipment("Mainhand", undefined);
              }
            }
          }
          return; // Allow block placement
        }
        palisadeCheck(e.block);
      }
    },
  });
  //Fences / SLABS - ON DESTROY
  event.blockComponentRegistry.registerCustomComponent("float_fc:on_player_destroy", {
    onPlayerDestroy(e) {
      try {
        //fence Destroy - MAYBE REMOVE LATER ADD TO EVENT
        if (fenceinv.has(e.block.above().typeId)) {
          e.block.above().setType("minecraft:air");
          return;
        } else if (fenceTypes.has(e.block.below().typeId)) {
          e.block.setPermutation(
            BlockPermutation.resolve(e.block.below().typeId + "_inventory", { "float_fc:post": 1 })
          );
          return;
        }
        selectedItem = e.player.getComponent("equippable").getEquipment("Mainhand");
        selectedItem = undefined;
        slabItem = e.destroyedBlockPermutation.getItemStack(1);
        if (ForestrySlabs.has(slabItem.typeId)) {
          e.player.dimension.spawnItem(slabItem, e.block.location);
        }
      } catch (e) {}
      slabItem = undefined;
    },
  });
  //Slab checker
  event.blockComponentRegistry.registerCustomComponent("float_fc:on_interact_slab", {
    onPlayerInteract(e) {
      try {
        let equipment = e.player.getComponent("equippable");
        let selectedItem = equipment?.getEquipment("Mainhand");

        // Check if the held item is a valid slab
        if (ForestrySlabs.has(selectedItem?.typeId)) {
          const currentHalf = e.block.permutation.getState("minecraft:vertical_half");
          const isDouble = e.block.permutation.getState("float_fc:double");

          // --- Case 1: Double Slab Formation ---
          if (
            !isDouble &&
            ((currentHalf === "bottom" && e.face === "Up") || (currentHalf === "top" && e.face === "Down"))
          ) {
            // Combine into a double slab
            consumeItem(e, equipment, selectedItem);
            e.block.setPermutation(e.block.permutation.withState("float_fc:double", true));
            e.player.playSound("use.wood");
            return;
          }

          // --- Case 2: Place Slab Above a 'Top' Slab ---
          if (e.face === "Up" && currentHalf === "top") {
            const aboveBlock = e.block.above();
            if (aboveBlock.typeId === "minecraft:air") {
              // Place a new slab with 'bottom' vertical_half above
              const newPermutation = BlockPermutation.resolve(selectedItem.typeId, {
                "minecraft:vertical_half": "bottom",
                "float_fc:double": false,
              });

              aboveBlock.setPermutation(newPermutation);
              consumeItem(e, equipment, selectedItem);
              e.player.playSound("use.wood");
              return;
            }
          }

          // --- Case 3: Place Slab Below a 'Bottom' Slab ---
          if (e.face === "Down" && currentHalf === "bottom") {
            const belowBlock = e.block.below();
            if (belowBlock.typeId === "minecraft:air") {
              // Place a new slab with 'top' vertical_half below
              const newPermutation = BlockPermutation.resolve(selectedItem.typeId, {
                "minecraft:vertical_half": "top",
                "float_fc:double": false,
              });

              belowBlock.setPermutation(newPermutation);
              consumeItem(e, equipment, selectedItem);
              e.player.playSound("use.wood");
              return;
            }
          }

          // --- Case 4: Side Placement ---
          let targetBlock;
          let face = e.face;

          if (face === "North") {
            targetBlock = e.block.north();
          } else if (face === "South") {
            targetBlock = e.block.south();
          } else if (face === "East") {
            targetBlock = e.block.east();
          } else if (face === "West") {
            targetBlock = e.block.west();
          }

          // Place a new slab on the side, matching the current half
          if (targetBlock && targetBlock.typeId === "minecraft:air") {
            const newPermutation = BlockPermutation.resolve(selectedItem.typeId, {
              "minecraft:vertical_half": currentHalf, // Match current half for side placement
              "float_fc:double": false,
            });

            targetBlock.setPermutation(newPermutation);
            consumeItem(e, equipment, selectedItem);
            e.player.playSound("use.wood");
            return;
          }
        }
      } catch (err) {
        //console.error(err);
      }
    },
  });

  // --- Helper Function for Item Consumption ---
  function consumeItem(e, equipment, selectedItem) {
    if (e.player.getGameMode() !== "creative") {
      if (selectedItem.amount > 1) {
        selectedItem.amount -= 1;
        equipment.setEquipment("Mainhand", selectedItem);
      } else {
        equipment.setEquipment("Mainhand", undefined);
      }
    }
  }

  //fence Interact
  event.blockComponentRegistry.registerCustomComponent("float_fc:on_interact", {
    onPlayerInteract(e) {
      try {
        const equipment = e.player.getComponent("equippable");
        const selectedItem = equipment?.getEquipment("Mainhand");

        // Get the type ID of the item the player is holding
        const selectedFence = selectedItem.typeId.replace("_inventory_2", "");
        const selectedType = selectedItem.typeId;

        let above = e.block.above();
        let newblock = e.block;

        // --- Handle Fence Gate Placement ---
        if (gateTypes.has(selectedType)) {
          // If the selected item is a fence gate, determine the correct rotation
          const direction = determineGateDirection(e.player, e.face);
          const newPermutation = BlockPermutation.resolve(selectedType, {
            "minecraft:cardinal_direction": direction,
            "float_fc:open": false, // Initially closed
          });

          // Place the fence gate in the proper position based on interaction face
          if (e.face === "North") {
            e.block.north().setPermutation(newPermutation);
            newblock = e.block.north();
          } else if (e.face === "South") {
            e.block.south().setPermutation(newPermutation);
            newblock = e.block.south();
          } else if (e.face === "East") {
            e.block.east().setPermutation(newPermutation);
            newblock = e.block.east();
          } else if (e.face === "West") {
            e.block.west().setPermutation(newPermutation);
            newblock = e.block.west();
          } else if (e.face === "Down") {
            e.block.below().setPermutation(newPermutation);
            newblock = e.block.below();
          } else {
            above.setPermutation(newPermutation);
            newblock = above;
          }

          // Update fences to adjust connections
          updateFences(e.block);
          updateFences(newblock);

          ["north", "east", "south", "west"].forEach((direction) => {
            const neighbor = newblock[direction]();
            if (fenceTypes.has(neighbor.typeId)) {
              updateFences(neighbor);
            }
          });

          // Handle item consumption if the player is not in creative mode
          if (e.player.getGameMode() !== "creative") {
            if (selectedItem.amount > 1) {
              selectedItem.amount -= 1;
              equipment.setEquipment("Mainhand", selectedItem);
            } else {
              equipment.setEquipment("Mainhand", undefined);
            }
          }
          return; // Exit early after handling the fence gate placement
        }

        // --- Handle Regular Fence Placement ---
        // Ensure the interaction is on the top face
        if (e.face !== "Up") {
          if (e.face === "North") {
            const northblock = e.block.north();
            if (northblock.above().typeId === "minecraft:air") {
              above.setType("minecraft:air");
              above
                .north()
                .setPermutation(BlockPermutation.resolve(e.block.typeId + "_inventory", { "float_fc:post": 1 }));
            }
            e.block.north().setPermutation(BlockPermutation.resolve(selectedFence));
            updateFences(e.block);
            updateFences(e.block.north());
            newblock = e.block.north();
          } else if (e.face === "South") {
            const northblock = e.block.south();
            if (e.block.south().above().typeId === "minecraft:air") {
              above
                .south()
                .setPermutation(BlockPermutation.resolve(e.block.typeId + "_inventory", { "float_fc:post": 1 }));
            }
            e.block.south().setPermutation(BlockPermutation.resolve(selectedFence));
            updateFences(e.block);
            updateFences(e.block.south());
            newblock = e.block.south();
          } else if (e.face === "East") {
            if (e.block.east().above().typeId === "minecraft:air") {
              above
                .east()
                .setPermutation(BlockPermutation.resolve(e.block.typeId + "_inventory", { "float_fc:post": 1 }));
            }
            e.block.east().setPermutation(BlockPermutation.resolve(selectedFence));
            updateFences(e.block);
            updateFences(e.block.east());
            newblock = e.block.east();
          } else if (e.face === "West") {
            if (e.block.west().above().typeId === "minecraft:air") {
              above
                .west()
                .setPermutation(BlockPermutation.resolve(e.block.typeId + "_inventory", { "float_fc:post": 1 }));
            }
            e.block.west().setPermutation(BlockPermutation.resolve(selectedFence));
            updateFences(e.block);
            updateFences(e.block.west());
            newblock = e.block.west();
          } else if (e.face === "Down") {
            e.block.below().setPermutation(BlockPermutation.resolve(selectedFence));
            updateFences(e.block);
            updateFences(e.block.below());
            newblock = e.block.below();
          }

          ["north", "east", "south", "west"].forEach((direction) => {
            const neighbor = newblock[direction]();
            if (fenceTypes.has(neighbor.typeId)) {
              updateFences(neighbor);
            }
          });
          if (e.player.getGameMode() !== "creative") {
            if (selectedItem.amount > 1) {
              selectedItem.amount -= 1;
              equipment.setEquipment("Mainhand", selectedItem);
            } else {
              equipment.setEquipment("Mainhand", undefined);
            }
          }
          return;
        }

        if (selectedItem && BlockTypes.get(selectedItem.typeId)) {
          const aboveBlock = e.block.above();

          if (fenceinv.has(aboveBlock.typeId)) {
            aboveBlock.setType(selectedItem.typeId.replace("_inventory_2", ""));
            e.block
              .above(2)
              .setPermutation(BlockPermutation.resolve(e.block.typeId + "_inventory", { "float_fc:post": 1 }));
            updateFences(aboveBlock);

            ["north", "east", "south", "west"].forEach((direction) => {
              const neighbor = aboveBlock[direction]();
              if (fenceTypes.has(neighbor.typeId)) {
                updateFences(neighbor);
              }
            });

            if (e.player.getGameMode() !== "creative") {
              if (selectedItem.amount > 1) {
                selectedItem.amount -= 1;
                equipment.setEquipment("Mainhand", selectedItem);
              } else {
                equipment.setEquipment("Mainhand", undefined);
              }
            }
          }
        }
      } catch (err) {}
    },
  });

  function determineGateDirection(player, face) {
    const rotation = player.getRotation().y;
    if (face === "North") {
      return rotation > 90 && rotation < 270 ? "west" : "east"; // Rotated 90 degrees
    } else if (face === "South") {
      return rotation > 90 && rotation < 270 ? "east" : "west"; // Rotated 90 degrees
    } else if (face === "East") {
      return rotation > 0 && rotation < 180 ? "north" : "south"; // Rotated 90 degrees
    } else if (face === "West") {
      return rotation > 0 && rotation < 180 ? "south" : "north"; // Rotated 90 degrees
    }

    return "north"; // Default fallback
  }

  //fence Place
  event.blockComponentRegistry.registerCustomComponent("float_fc:on_player_placed_fence", {
    onPlace(e) {
      try {
        // Set the block type of the placed fence
        e.block.setType(e.block.typeId.replace("_inventory_2", ""));

        if (e.block.above().typeId === "minecraft:air") {
          // Copy block states from the placed fence to the inventory block
          const permutation = e.block.permutation;
          e.block
            .above()
            .setPermutation(BlockPermutation.resolve(e.block.typeId + "_inventory", { "float_fc:post": 1 }));
        }
      } catch (err) {
        console.error("Error in on_player_placed_fence:", err);
      }
    },
  });

  //Fence Gate Place
  event.blockComponentRegistry.registerCustomComponent("float_fc:on_player_placed_gate", {
    onPlace(e) {
      try {
        currentStates = e.block.permutation.getAllStates();
        cardinalDirection = currentStates["minecraft:cardinal_direction"];
        if (cardinalDirection == "south") {
          currentStates["float_fc:direction"] = true;
          e.block.setPermutation(BlockPermutation.resolve(e.block.typeId, currentStates));
        }
        // Check if the above block is air and handle multiple types of fence gates
        if (e.block.above().typeId === "minecraft:air" && gateTypes.has(e.block.typeId)) {
          var newAboveStates = undefined;
          newAboveStates = { ...currentStates };
          if (cardinalDirection == "south") {
            delete newAboveStates["minecraft:cardinal_direction"];
          }
          newAboveStates["float_fc:invisible"] = true;
          e.block.above().setPermutation(BlockPermutation.resolve(e.block.typeId, newAboveStates));
          newAboveStates = undefined;
        }
      } catch (e) {}
      currentStates = cardinalDirection = undefined;
    },
  });
  //Fence Gate Interact
  event.blockComponentRegistry.registerCustomComponent("float_fc:on_interact_gate", {
    onPlayerInteract(e) {
      try {
        const equipment = e.player.getComponent("equippable");
        const selectedItem = equipment?.getEquipment("Mainhand");

        // Check if the selected item is valid and the player interacts from the top
        if (selectedItem && e.face === "Up" && BlockTypes.get(selectedItem.typeId)) {
          const aboveBlock = e.block.above();

          // Check if the block above is one of the fence gate types in the set
          if (gateTypes.has(aboveBlock.typeId)) {
            aboveBlock.setType(selectedItem.typeId);

            // Handle item consumption if not in creative mode
            if (e.player.getGameMode() !== "creative") {
              if (selectedItem.amount > 1) {
                selectedItem.amount -= 1;
                equipment.setEquipment("Mainhand", selectedItem);
              } else {
                equipment.setEquipment("Mainhand", undefined);
              }
            }
            return;
          }
        }

        // Toggle open state while preserving the original direction
        const currentDirection = e.block.permutation.getState("minecraft:cardinal_direction");
        const newOpenState = !e.block.permutation.getState("float_fc:open");

        const playerDirection = determineOutwardDirection(e.player, e.block);
        const adjustedDirection = currentDirection === playerDirection ? currentDirection : currentDirection;

        const newPermutation = BlockPermutation.resolve(e.block.typeId, {
          ...e.block.permutation.getAllStates(),
          "float_fc:open": newOpenState,
          "minecraft:cardinal_direction": adjustedDirection,
        });

        e.block.setPermutation(newPermutation);

        // Play the appropriate sound
        e.block.dimension.playSound(newOpenState ? "open.fence_gate" : "close.fence_gate", e.block.location);

        // Update the gate above if applicable
        const aboveBlock = e.block.above();
        if (gateTypes.has(aboveBlock.typeId) && aboveBlock.permutation.getState("float_fc:invisible")) {
          if (aboveBlock.permutation.getState("float_fc:open") !== newOpenState) {
            const abovePermutation = BlockPermutation.resolve(aboveBlock.typeId, {
              ...aboveBlock.permutation.getAllStates(),
              "float_fc:open": newOpenState,
            });
            aboveBlock.setPermutation(abovePermutation);
          }
        }
      } catch (err) {
        //console.error(err);
      }
    },
  });

  //Fence Gate Destory
  event.blockComponentRegistry.registerCustomComponent("float_fc:on_player_destroy_gate", {
    onPlayerDestroy(e) {
      try {
        aboveBlock = e.block.above();
        // Check if the above block is one of the fence gate types in the set and is invisible
        if (gateTypes.has(aboveBlock.typeId) && aboveBlock.permutation.getState("float_fc:invisible")) {
          aboveBlock.setType("minecraft:air");
        }
      } catch (e) {}
      aboveBlock = undefined;
    },
  });
  //Jam Add
  event.blockComponentRegistry.registerCustomComponent("float_fc:jam_placement", {
    onPlayerInteract(e) {
      try {
        const jamblock = e.block;
        const jamtype = e.player.getComponent("equippable")?.getEquipment("Mainhand")?.typeId;

        if (
          jamblock.permutation.getState("float_fc:jars") < 4 &&
          jamtype &&
          JamItems.has(jamtype) && // Ensure the item in hand is a valid jam item
          jamtype.includes(jamblock.typeId.split(":")[1].replace("_jam_block", "")) // Ensure the block matches the item in hand
        ) {
          const newPermutation = BlockPermutation.resolve(jamblock.typeId, {
            "float_fc:jars": jamblock.permutation.getState("float_fc:jars") + 1,
            "minecraft:cardinal_direction": jamblock.permutation.getState("minecraft:cardinal_direction"),
          });

          if (newPermutation) {
            jamblock.setPermutation(newPermutation);
          }

          if (e.player.getGameMode() !== "creative") {
            const equipment = e.player.getComponent("equippable");
            const selectedItem = equipment?.getEquipment("Mainhand");

            if (selectedItem?.amount > 1) {
              selectedItem.amount -= 1;
              equipment.setEquipment("Mainhand", selectedItem);
            } else {
              equipment.setEquipment("Mainhand", undefined);
            }
          }
        }
      } catch (error) {
        console.error("Error during jam placement interaction:", error);
      }
    },
  }); //Fence Gate Wall Detection
  event.blockComponentRegistry.registerCustomComponent("float_fc:gate_wall_detection", {
    // Use static counter instead of instance-based counter
    onPlace(e) {
      adjustFenceGateHeight(e.block);
    },
    onTick(e) {
      adjustFenceGateHeight(e.block);
    },
  });
});

//Breaking Block Control
function handleBeforePlayerBreakQuarter(e) {
  if (!e.block.typeId.endsWith("_quarter_plank")) {
    return;
  }
  const player = e.player;
  const onplace = true;
  const viewDirection = player.getViewDirection();
  const startPosition = player.getHeadLocation();
  const rayLength = 10; // Adjust the ray length as needed
  const rayDirection = {
    x: viewDirection.x,
    y: viewDirection.y,
    z: viewDirection.z,
  };

  const rayOptions = {
    maxDistance: rayLength,
    includeLiquidBlocks: false,
    includePassableBlocks: true,
  };

  const blockHit = player.dimension.getBlockFromRay(startPosition, rayDirection, rayOptions);
  if (blockHit) {
    const faceLocation = blockHit.faceLocation;
    const blockLocation = blockHit.block.location;
    const combinedLocation = {
      x: blockLocation.x + faceLocation.x,
      y: blockLocation.y + faceLocation.y,
      z: blockLocation.z + faceLocation.z,
    };

    const equipment = e.player.getComponent("equippable");
    const selectedItem = equipment?.getEquipment("Mainhand");

    system.run(() => {
      quarterDestroy(e.block, combinedLocation, blockHit.face, onplace, player, e.block.permutation);
      handleDurabilityVanilla(e.player, 1);
    });
    e.cancel = true; // Prevent the default placement behavior
  } else {
    console.log("No block was hit by the ray.");
  }
}
world.beforeEvents.playerBreakBlock.subscribe(handleBeforePlayerBreakQuarter);

function quarterDestroy(quarterBlock, faceLocation, face, onplace, player, destroyedBlockPermutation) {
  destroyQuarter(quarterBlock, faceLocation, face, player, destroyedBlockPermutation);
}

function quarterPlace(quarterBlock, faceLocation, face, onplace, player, permutationToPlace) {
  if (onplace) {
    placeQuarter(quarterBlock, faceLocation, face, player, permutationToPlace);
  } else {
    updateQuarter(quarterBlock, faceLocation, face);
  }
}

function determineOutwardDirection(player, block) {
  const playerLocation = player.location;
  const blockLocation = block.location;

  const dx = playerLocation.x - blockLocation.x;
  const dz = playerLocation.z - blockLocation.z;

  if (Math.abs(dx) > Math.abs(dz)) {
    return dx > 0 ? "west" : "east"; // Player is on the east or west side
  } else {
    return dz > 0 ? "north" : "south"; // Player is on the north or south side
  }
}

function updateBlocksCheck(event) {
  try {
    if (doorTypes.has(event.block.typeId) && !event.block.above().permutation.getState("float_fc:upper_block_bit")) {
      if (event.block.above().typeId !== "minecraft:air") {
        event.block.setType("minecraft:air");
      }
    } else {
      if (fenceTypes.has(event.block.typeId)) {
        updateFences(event.block);
      }
      if (fenceTypes.has(event.block.north().typeId)) {
        updateFences(event.block.north());
      }
      if (fenceTypes.has(event.block.east().typeId)) {
        updateFences(event.block.east());
      }
      if (fenceTypes.has(event.block.south().typeId)) {
        updateFences(event.block.south());
      }
      if (fenceTypes.has(event.block.west().typeId)) {
        updateFences(event.block.west());
      }
      if (isCustomPalisade(event.block.below())) {
        updatePalisade(event.block.below());
      }
    }
  } catch (e) {
    return;
  }
}

var north,
  east,
  south,
  west = undefined;
var northConnects,
  eastConnects,
  southConnects,
  westConnects = false;
function updateFences(fenceblock) {
  try {
    // Check if the block above should be converted to an inventory version
    if (fenceblock.typeId === "float_fc:fence" && fenceblock.above().typeId === "minecraft:air") {
      const permutation = fenceblock.permutation; // Get the permutation of the current fence
      const states = {
        "float_fc:north_picket": permutation.getState("float_fc:north_picket"),
        "float_fc:south_picket": permutation.getState("float_fc:south_picket"),
        "float_fc:east_picket": permutation.getState("float_fc:east_picket"),
        "float_fc:west_picket": permutation.getState("float_fc:west_picket"),
        "float_fc:post": permutation.getState("float_fc:post"),
      };

      // Apply these states to the inventory block
      fenceblock.above().setPermutation(BlockPermutation.resolve(fenceblock.typeId + "_inventory", states));
    }

    // Neighboring connections for the fence block itself (no changes here)
    north = fenceblock.north();
    east = fenceblock.east();
    south = fenceblock.south();
    west = fenceblock.west();
    northConnects = !fenceexcludeBlocksArray.has(north?.typeId);
    eastConnects = !fenceexcludeBlocksArray.has(east?.typeId);
    southConnects = !fenceexcludeBlocksArray.has(south?.typeId);
    westConnects = !fenceexcludeBlocksArray.has(west?.typeId);

    // Update block states for the current fence block
    fenceblock.setPermutation(fenceblock.permutation.withState("float_fc:north_picket", northConnects ? 1 : 0));
    fenceblock.setPermutation(fenceblock.permutation.withState("float_fc:south_picket", southConnects ? 1 : 0));
    fenceblock.setPermutation(fenceblock.permutation.withState("float_fc:east_picket", eastConnects ? 1 : 0));
    fenceblock.setPermutation(fenceblock.permutation.withState("float_fc:west_picket", westConnects ? 1 : 0));

    // Check if the block above is in the fenceinv set and update its states
    if (fenceinv.has(fenceblock.above().typeId)) {
      const inventoryStates = {
        "float_fc:north_picket": fenceblock.permutation.getState("float_fc:north_picket"),
        "float_fc:south_picket": fenceblock.permutation.getState("float_fc:south_picket"),
        "float_fc:east_picket": fenceblock.permutation.getState("float_fc:east_picket"),
        "float_fc:west_picket": fenceblock.permutation.getState("float_fc:west_picket"),
        "float_fc:post": fenceblock.permutation.getState("float_fc:post"),
      };

      fenceblock.above().setPermutation(BlockPermutation.resolve(fenceblock.typeId + "_inventory", inventoryStates));
    }
  } catch (err) {}

  // Reset neighbors
  north = east = south = west = undefined;
}

var block,
  northBlock,
  southBlock,
  eastBlock,
  westBlock,
  shape,
  cardinal_direction = undefined;
function updateStair(stairBlock) {
  try {
    block = stairBlock;
    northBlock = block.north();
    southBlock = block.south();
    eastBlock = block.east();
    westBlock = block.west();
    shape = block.permutation.getState("float_fc:shape");
    cardinal_direction = block.permutation.getState("minecraft:cardinal_direction");
    block.setPermutation(block.permutation.withState("float_fc:placed_bit", true));
    if (cardinal_direction == "north") {
      if (isCustomStairs(southBlock) && southBlock.hasTag("custom_stairs_east") && shape == "straight") {
        block.setPermutation(block.permutation.withState("float_fc:shape", "inner_right"));
      } else if (!isCustomStairs(southBlock) && !southBlock.hasTag("custom_stairs_east") && shape == "inner_right") {
        block.setPermutation(block.permutation.withState("float_fc:shape", "straight"));
      } else if (isCustomStairs(southBlock) && southBlock.hasTag("custom_stairs_west") && shape == "straight") {
        block.setPermutation(block.permutation.withState("float_fc:shape", "inner_left"));
      } else if (!isCustomStairs(southBlock) && !southBlock.hasTag("custom_stairs_west") && shape == "inner_left") {
        block.setPermutation(block.permutation.withState("float_fc:shape", "straight"));
      } else if (isCustomStairs(northBlock) && northBlock.hasTag("custom_stairs_west") && shape == "straight") {
        block.setPermutation(block.permutation.withState("float_fc:shape", "outer_right"));
      } else if (!isCustomStairs(northBlock) && !northBlock.hasTag("custom_stairs_west") && shape == "outer_right") {
        block.setPermutation(block.permutation.withState("float_fc:shape", "straight"));
      } else if (isCustomStairs(northBlock) && northBlock.hasTag("custom_stairs_east") && shape == "straight") {
        block.setPermutation(block.permutation.withState("float_fc:shape", "outer_left"));
      } else if (!isCustomStairs(northBlock) && !northBlock.hasTag("custom_stairs_east") && shape == "outer_left") {
        block.setPermutation(block.permutation.withState("float_fc:shape", "straight"));
      }
    } else if (cardinal_direction == "south") {
      if (isCustomStairs(northBlock) && northBlock.hasTag("custom_stairs_west") && shape == "straight") {
        block.setPermutation(block.permutation.withState("float_fc:shape", "inner_left"));
      } else if (!isCustomStairs(northBlock) && !northBlock.hasTag("custom_stairs_west") && shape == "inner_left") {
        block.setPermutation(block.permutation.withState("float_fc:shape", "straight"));
      } else if (isCustomStairs(northBlock) && northBlock.hasTag("custom_stairs_east") && shape == "straight") {
        block.setPermutation(block.permutation.withState("float_fc:shape", "inner_right"));
      } else if (!isCustomStairs(northBlock) && !northBlock.hasTag("custom_stairs_east") && shape == "inner_right") {
        block.setPermutation(block.permutation.withState("float_fc:shape", "straight"));
      } else if (isCustomStairs(southBlock) && southBlock.hasTag("custom_stairs_west") && shape == "straight") {
        block.setPermutation(block.permutation.withState("float_fc:shape", "outer_right"));
      } else if (!isCustomStairs(southBlock) && !southBlock.hasTag("custom_stairs_west") && shape == "outer_right") {
        block.setPermutation(block.permutation.withState("float_fc:shape", "straight"));
      } else if (isCustomStairs(southBlock) && southBlock.hasTag("custom_stairs_east") && shape == "straight") {
        block.setPermutation(block.permutation.withState("float_fc:shape", "outer_left"));
      } else if (!isCustomStairs(southBlock) && !southBlock.hasTag("custom_stairs_east") && shape == "outer_left") {
        block.setPermutation(block.permutation.withState("float_fc:shape", "straight"));
      }
    } else if (cardinal_direction == "west") {
      if (isCustomStairs(eastBlock) && eastBlock.hasTag("custom_stairs_south") && shape == "straight") {
        block.setPermutation(block.permutation.withState("float_fc:shape", "inner_left"));
      } else if (!isCustomStairs(eastBlock) && !eastBlock.hasTag("custom_stairs_south") && shape == "inner_left") {
        block.setPermutation(block.permutation.withState("float_fc:shape", "straight"));
      } else if (isCustomStairs(eastBlock) && eastBlock.hasTag("custom_stairs_north") && shape == "straight") {
        block.setPermutation(block.permutation.withState("float_fc:shape", "inner_right"));
      } else if (!isCustomStairs(eastBlock) && !eastBlock.hasTag("custom_stairs_north") && shape == "inner_right") {
        block.setPermutation(block.permutation.withState("float_fc:shape", "straight"));
      } else if (isCustomStairs(westBlock) && westBlock.hasTag("custom_stairs_north") && shape == "straight") {
        block.setPermutation(block.permutation.withState("float_fc:shape", "outer_right"));
      } else if (!isCustomStairs(westBlock) && !westBlock.hasTag("custom_stairs_north") && shape == "outer_right") {
        block.setPermutation(block.permutation.withState("float_fc:shape", "straight"));
      } else if (isCustomStairs(westBlock) && westBlock.hasTag("custom_stairs_south") && shape == "straight") {
        block.setPermutation(block.permutation.withState("float_fc:shape", "outer_left"));
      } else if (!isCustomStairs(westBlock) && !westBlock.hasTag("custom_stairs_south") && shape == "outer_left") {
        block.setPermutation(block.permutation.withState("float_fc:shape", "straight"));
      }
    } else if (cardinal_direction == "east") {
      if (isCustomStairs(westBlock) && westBlock.hasTag("custom_stairs_north") && shape == "straight") {
        block.setPermutation(block.permutation.withState("float_fc:shape", "inner_left"));
      } else if (!isCustomStairs(westBlock) && !westBlock.hasTag("custom_stairs_north") && shape == "inner_left") {
        block.setPermutation(block.permutation.withState("float_fc:shape", "straight"));
      } else if (isCustomStairs(westBlock) && westBlock.hasTag("custom_stairs_south") && shape == "straight") {
        block.setPermutation(block.permutation.withState("float_fc:shape", "inner_right"));
      } else if (!isCustomStairs(westBlock) && !westBlock.hasTag("custom_stairs_south") && shape == "inner_right") {
        block.setPermutation(block.permutation.withState("float_fc:shape", "straight"));
      } else if (isCustomStairs(eastBlock) && eastBlock.hasTag("custom_stairs_south") && shape == "straight") {
        block.setPermutation(block.permutation.withState("float_fc:shape", "outer_right"));
      } else if (!isCustomStairs(eastBlock) && !eastBlock.hasTag("custom_stairs_south") && shape == "outer_right") {
        block.setPermutation(block.permutation.withState("float_fc:shape", "straight"));
      } else if (isCustomStairs(eastBlock) && eastBlock.hasTag("custom_stairs_north") && shape == "straight") {
        block.setPermutation(block.permutation.withState("float_fc:shape", "outer_left"));
      } else if (!isCustomStairs(eastBlock) && !eastBlock.hasTag("custom_stairs_north") && shape == "outer_left") {
        block.setPermutation(block.permutation.withState("float_fc:shape", "straight"));
      }
    }
  } catch (e) {}
  block = northBlock = southBlock = eastBlock = westBlock = shape = cardinal_direction = undefined;
}

function shearPalisade(palisadeBlock, player) {
  const block = palisadeBlock;
  const isSheared = block.permutation.getState("float_fc:sheared");
  if (isSheared) {
    return;
  } else {
    palisadeBlock.dimension.playSound("use.wood", palisadeBlock.location);
    handleDurabilityVanilla(player, 1);
    block.setPermutation(block.permutation.withState("float_fc:sheared", true));
  }
}

function updatePath(pathBlock) {
  const block = pathBlock;
  const cardinalDirection = block.permutation.getState("minecraft:cardinal_direction"); // Retrieve cardinal direction
  const isWide = isCustomPathWide(block);

  let leftBlock = undefined;
  let rightBlock = undefined;

  // Determine left and right blocks based on cardinal direction
  if (cardinalDirection === "north") {
    leftBlock = block.west();
    rightBlock = block.east();
  } else if (cardinalDirection === "south") {
    leftBlock = block.east();
    rightBlock = block.west();
  } else if (cardinalDirection === "east") {
    leftBlock = block.north();
    rightBlock = block.south();
  } else if (cardinalDirection === "west") {
    leftBlock = block.south();
    rightBlock = block.north();
  }
  let isConnectedLeft = false;
  let isConnectedRight = false;

  // Check connections to the left and right based on the path type
  isConnectedLeft = leftBlock && (isWide ? isCustomPathWide(leftBlock) : isCustomPath(leftBlock));
  isConnectedRight = rightBlock && (isWide ? isCustomPathWide(rightBlock) : isCustomPath(rightBlock));

  // Update the block's states based on connections
  block.setPermutation(
    block.permutation
      .withState("float_fc:connected_left", isConnectedLeft)
      .withState("float_fc:connected_right", isConnectedRight)
  );
}

function updatePalisade(palisadeBlock) {
  const block = palisadeBlock;

  // Get the block above
  const aboveBlock = block.above();

  // Determine if there is a palisade block above and it's not air
  const hasAbove = aboveBlock && aboveBlock.typeId !== "minecraft:air";

  // Update the block's states
  block.setPermutation(
    block.permutation
      .withState("float_fc:top", !hasAbove) // Top is true only if there is no block above
      .withState("float_fc:bottom", hasAbove) // Bottom is true only if there is a block above
  );
}

function updateQuarter(quarterBlock, FaceLocation, face, player) {
  const block = quarterBlock;

  const dirKey = `float_fc:dir_${block.location.x}_${block.location.y}_${block.location.z}`;
  const cardinalDirection = world.getDynamicProperty(dirKey) || "north"; // fallback if not stored

  const verticalHalf = block.permutation.getState("minecraft:vertical_half");
  //console.error("§2§lCardinal Direction: " + cardinalDirection);

  // Check if the interaction is on a whole block face
  const isTopBottomWholeBlockFace = FaceLocation.y % 1 === 0;

  // Check if the interaction is on the side of a whole block
  const isSideOfWholeBlock = FaceLocation.x % 1 === 0 || FaceLocation.z % 1 === 0;

  // Determine the target block's location based on the cardinal direction and face
  let targetLocation = { ...block.location };
  let placedquarter = false;

  targetLocation = {
    x: Math.floor(block.location.x),
    y: Math.floor(block.location.y),
    z: Math.floor(block.location.z),
  };

  const targetBlock = block.dimension.getBlock(targetLocation);

  // Determine which quarter segment to update based on the face interacted with
  let updatedState = {};

  // Check if the quarter block already has more than one bottom_quarter_[1_4] traits set
  const bottomQuarters = [
    block.permutation.getState("float_fc:bottom_quarter_1"),
    block.permutation.getState("float_fc:bottom_quarter_2"),
    block.permutation.getState("float_fc:bottom_quarter_3"),
    block.permutation.getState("float_fc:bottom_quarter_4"),
  ];
  const topQuarters = [
    block.permutation.getState("float_fc:top_quarter_1"),
    block.permutation.getState("float_fc:top_quarter_2"),
    block.permutation.getState("float_fc:top_quarter_3"),
    block.permutation.getState("float_fc:top_quarter_4"),
  ];

  const activeBottomQuarters = bottomQuarters.filter(Boolean).length;
  const activeTopQuarters = topQuarters.filter(Boolean).length;
  const relativeX = FaceLocation.x - Math.floor(FaceLocation.x);
  const relativeZ = FaceLocation.z - Math.floor(FaceLocation.z);
  const isBottomHalf = FaceLocation.y - Math.floor(FaceLocation.y) < 0.5;
  const isTopHalf = FaceLocation.y - Math.floor(FaceLocation.y) >= 0.5;

  if (face === "Up") {
    if (
      !isTopBottomWholeBlockFace &&
      relativeX < 0.5 &&
      relativeZ < 0.5 &&
      !block.permutation.getState("float_fc:bottom_quarter_1") &&
      block.permutation.getState("float_fc:bottom_quarter_2")
    ) {
      updatedState = { "float_fc:bottom_quarter_1": true };
      placedquarter = true;
    } else if (
      !isTopBottomWholeBlockFace &&
      relativeX >= 0.5 &&
      relativeZ < 0.5 &&
      !block.permutation.getState("float_fc:bottom_quarter_2") &&
      block.permutation.getState("float_fc:bottom_quarter_1")
    ) {
      updatedState = { "float_fc:bottom_quarter_2": true };
      placedquarter = true;
    } else if (
      !isTopBottomWholeBlockFace &&
      relativeX >= 0.5 &&
      relativeZ >= 0.5 &&
      !block.permutation.getState("float_fc:bottom_quarter_3") &&
      block.permutation.getState("float_fc:bottom_quarter_4")
    ) {
      updatedState = { "float_fc:bottom_quarter_3": true };
      placedquarter = true;
    } else if (
      !isTopBottomWholeBlockFace &&
      relativeX < 0.5 &&
      relativeZ >= 0.5 &&
      !block.permutation.getState("float_fc:bottom_quarter_4") &&
      block.permutation.getState("float_fc:bottom_quarter_3")
    ) {
      updatedState = { "float_fc:bottom_quarter_4": true };
      placedquarter = true;
    } else placedquarter = false;

    if (!placedquarter) {
      if (relativeX < 0.5 && relativeZ < 0.5) {
        updatedState = { "float_fc:top_quarter_1": true };
      } else if (relativeX >= 0.5 && relativeZ < 0.5) {
        updatedState = { "float_fc:top_quarter_2": true };
      } else if (relativeX < 0.5 && relativeZ >= 0.5) {
        updatedState = { "float_fc:top_quarter_4": true };
      } else {
        updatedState = { "float_fc:top_quarter_3": true };
      }
    }
  } else if (face === "Down") {
    if (
      !isTopBottomWholeBlockFace &&
      relativeX < 0.5 &&
      relativeZ < 0.5 &&
      !block.permutation.getState("float_fc:top_quarter_1") &&
      block.permutation.getState("float_fc:top_quarter_2")
    ) {
      updatedState = { "float_fc:top_quarter_1": true };
      placedquarter = true;
    } else if (
      !isTopBottomWholeBlockFace &&
      relativeX >= 0.5 &&
      relativeZ < 0.5 &&
      !block.permutation.getState("float_fc:top_quarter_2") &&
      block.permutation.getState("float_fc:top_quarter_1")
    ) {
      updatedState = { "float_fc:top_quarter_2": true };
      placedquarter = true;
    } else if (
      !isTopBottomWholeBlockFace &&
      relativeX >= 0.5 &&
      relativeZ >= 0.5 &&
      !block.permutation.getState("float_fc:top_quarter_3") &&
      block.permutation.getState("float_fc:top_quarter_4")
    ) {
      updatedState = { "float_fc:top_quarter_3": true };
      placedquarter = true;
    } else if (
      !isTopBottomWholeBlockFace &&
      relativeX < 0.5 &&
      relativeZ >= 0.5 &&
      !block.permutation.getState("float_fc:top_quarter_4") &&
      block.permutation.getState("float_fc:top_quarter_3")
    ) {
      updatedState = { "float_fc:top_quarter_4": true };
      placedquarter = true;
    } else placedquarter = false;
    if (!placedquarter) {
      if (relativeX < 0.5 && relativeZ < 0.5) {
        updatedState = { "float_fc:bottom_quarter_1": true };
      } else if (relativeX >= 0.5 && relativeZ < 0.5) {
        updatedState = { "float_fc:bottom_quarter_2": true };
      } else if (relativeX < 0.5 && relativeZ >= 0.5) {
        updatedState = { "float_fc:bottom_quarter_4": true };
      } else {
        updatedState = { "float_fc:bottom_quarter_3": true };
      }
    }
  } else if (isBottomHalf) {
    if (activeBottomQuarters >= 1) {
      switch (face) {
        case "North":
          if (
            !isSideOfWholeBlock &&
            !block.permutation.getState("float_fc:bottom_quarter_4") &&
            block.permutation.getState("float_fc:top_quarter_4") &&
            relativeX < 0.5
          ) {
            updatedState = { "float_fc:bottom_quarter_4": true };
          } else if (
            !isSideOfWholeBlock &&
            !block.permutation.getState("float_fc:bottom_quarter_3") &&
            block.permutation.getState("float_fc:top_quarter_3") &&
            relativeX > 0.5
          ) {
            updatedState = { "float_fc:bottom_quarter_3": true };
          } else {
            updatedState =
              relativeX < 0.5 ? { "float_fc:bottom_quarter_1": true } : { "float_fc:bottom_quarter_2": true };
          }
          break;
        case "South":
          if (
            !isSideOfWholeBlock &&
            !block.permutation.getState("float_fc:bottom_quarter_1") &&
            block.permutation.getState("float_fc:top_quarter_1") &&
            relativeX < 0.5
          ) {
            updatedState = { "float_fc:bottom_quarter_1": true };
          } else if (
            !isSideOfWholeBlock &&
            !block.permutation.getState("float_fc:bottom_quarter_2") &&
            block.permutation.getState("float_fc:top_quarter_2") &&
            relativeX > 0.5
          ) {
            updatedState = { "float_fc:bottom_quarter_2": true };
          } else {
            updatedState =
              relativeX < 0.5 ? { "float_fc:bottom_quarter_4": true } : { "float_fc:bottom_quarter_3": true };
          }
          break;
        case "East":
          if (
            !isSideOfWholeBlock &&
            !block.permutation.getState("float_fc:bottom_quarter_1") &&
            block.permutation.getState("float_fc:top_quarter_1") &&
            relativeZ < 0.5
          ) {
            updatedState = { "float_fc:bottom_quarter_1": true };
          } else if (
            !isSideOfWholeBlock &&
            !block.permutation.getState("float_fc:bottom_quarter_4") &&
            block.permutation.getState("float_fc:top_quarter_4") &&
            relativeZ > 0.5
          ) {
            updatedState = { "float_fc:bottom_quarter_4": true };
          } else {
            updatedState =
              relativeZ < 0.5 ? { "float_fc:bottom_quarter_2": true } : { "float_fc:bottom_quarter_3": true };
          }
          break;
        case "West":
          if (
            !isSideOfWholeBlock &&
            !block.permutation.getState("float_fc:bottom_quarter_2") &&
            block.permutation.getState("float_fc:top_quarter_2") &&
            relativeZ < 0.5
          ) {
            updatedState = { "float_fc:bottom_quarter_2": true };
          } else if (
            !isSideOfWholeBlock &&
            !block.permutation.getState("float_fc:bottom_quarter_3") &&
            block.permutation.getState("float_fc:top_quarter_3") &&
            relativeZ > 0.5
          ) {
            updatedState = { "float_fc:bottom_quarter_3": true };
          } else {
            updatedState =
              relativeZ < 0.5 ? { "float_fc:bottom_quarter_1": true } : { "float_fc:bottom_quarter_4": true };
          }
          break;
        default:
          console.error("Bottom quarter placement error.");
      }
    }
  } else if (isTopHalf) {
    if (activeTopQuarters >= 1) {
      switch (face) {
        case "North":
          if (
            !isSideOfWholeBlock &&
            !block.permutation.getState("float_fc:top_quarter_4") &&
            block.permutation.getState("float_fc:bottom_quarter_4") &&
            relativeX < 0.5
          ) {
            updatedState = { "float_fc:top_quarter_4": true };
          } else if (
            !isSideOfWholeBlock &&
            !block.permutation.getState("float_fc:top_quarter_3") &&
            block.permutation.getState("float_fc:bottom_quarter_3") &&
            relativeX > 0.5
          ) {
            updatedState = { "float_fc:top_quarter_3": true };
          } else {
            updatedState = relativeX < 0.5 ? { "float_fc:top_quarter_1": true } : { "float_fc:top_quarter_2": true };
          }

          break;
        case "South":
          if (
            !isSideOfWholeBlock &&
            !block.permutation.getState("float_fc:top_quarter_1") &&
            block.permutation.getState("float_fc:bottom_quarter_1") &&
            relativeX < 0.5
          ) {
            updatedState = { "float_fc:top_quarter_1": true };
          } else if (
            !isSideOfWholeBlock &&
            !block.permutation.getState("float_fc:top_quarter_2") &&
            block.permutation.getState("float_fc:bottom_quarter_2") &&
            relativeX > 0.5
          ) {
            updatedState = { "float_fc:top_quarter_2": true };
          } else {
            updatedState = relativeX < 0.5 ? { "float_fc:top_quarter_4": true } : { "float_fc:top_quarter_3": true };
          }
          break;
        case "East":
          if (
            !isSideOfWholeBlock &&
            !block.permutation.getState("float_fc:top_quarter_1") &&
            block.permutation.getState("float_fc:bottom_quarter_1") &&
            relativeZ < 0.5
          ) {
            updatedState = { "float_fc:top_quarter_1": true };
          } else if (
            !isSideOfWholeBlock &&
            !block.permutation.getState("float_fc:top_quarter_4") &&
            block.permutation.getState("float_fc:bottom_quarter_4") &&
            relativeZ > 0.5
          ) {
            updatedState = { "float_fc:top_quarter_4": true };
          } else {
            updatedState = relativeZ < 0.5 ? { "float_fc:top_quarter_2": true } : { "float_fc:top_quarter_3": true };
          }
          break;
        case "West":
          if (
            !isSideOfWholeBlock &&
            !block.permutation.getState("float_fc:top_quarter_2") &&
            block.permutation.getState("float_fc:bottom_quarter_2") &&
            relativeZ < 0.5
          ) {
            updatedState = { "float_fc:top_quarter_2": true };
          } else if (
            !isSideOfWholeBlock &&
            !block.permutation.getState("float_fc:top_quarter_3") &&
            block.permutation.getState("float_fc:bottom_quarter_3") &&
            relativeZ > 0.5
          ) {
            updatedState = { "float_fc:top_quarter_3": true };
          } else {
            updatedState = relativeZ < 0.5 ? { "float_fc:top_quarter_1": true } : { "float_fc:top_quarter_4": true };
          }
          break;
        default:
          console.error("Bottom quarter placement error.");
      }
    }
  } else {
    // Proceed with the original logic if there are not more than one bottom_quarter traits set
    switch (face) {
      case "North":
        updatedState = {
          ...updatedState,
          ...(cardinalDirection === "south" && verticalHalf === "bottom"
            ? { "float_fc:bottom_quarter_4": true }
            : cardinalDirection === "west" && verticalHalf === "bottom"
            ? { "float_fc:bottom_quarter_2": true }
            : { "float_fc:top_quarter_4": true }),
        };
        break;
      case "South":
        updatedState = {
          ...updatedState,
          ...(cardinalDirection === "north" && verticalHalf === "bottom"
            ? { "float_fc:bottom_quarter_4": true }
            : cardinalDirection === "east" && verticalHalf === "bottom"
            ? { "float_fc:bottom_quarter_2": true }
            : { "float_fc:top_quarter_2": true }),
        };
        break;
      case "East":
        updatedState = {
          ...updatedState,
          ...(cardinalDirection === "west" && verticalHalf === "bottom"
            ? { "float_fc:bottom_quarter_4": true }
            : cardinalDirection === "north" && verticalHalf === "bottom"
            ? { "float_fc:bottom_quarter_2": true }
            : { "float_fc:top_quarter_1": true }),
        };
        break;
      case "West":
        updatedState = {
          ...updatedState,
          ...(cardinalDirection === "south" && verticalHalf === "bottom"
            ? { "float_fc:bottom_quarter_2": true }
            : cardinalDirection === "east" && verticalHalf === "bottom"
            ? { "float_fc:bottom_quarter_4": true }
            : { "float_fc:top_quarter_3": true }),
        };
        break;
      default:
        console.error("Invalid face interaction.");
        return;
    }
  }

  // Check if the updated state matches the existing state
  const existingState = block.permutation.getAllStates();
  const isSameState = Object.entries(updatedState).every(([key, value]) => existingState[key] === value);
  let faceLocationMatches = true;

  if (isSameState) {
    // Update the block's permutation with the new state
    faceLocationMatches =
      Math.floor(FaceLocation.x) === Math.floor(block.location.x) &&
      Math.floor(FaceLocation.z) === Math.floor(block.location.z);
  }

  if (isSameState || !faceLocationMatches) {
    // Determine the direction of the face the player interacted with
    let newQuarterState = {};
    if (updatedState["float_fc:bottom_quarter_4"]) {
      if (cardinalDirection === "north") {
        if (face === "North") {
          newQuarterState = { "float_fc:bottom_quarter_3": true };
        } else if (face === "West") {
          newQuarterState = { "float_fc:bottom_quarter_3": true };
        } else if (face === "East") {
          newQuarterState = { "float_fc:bottom_quarter_2": true };
        } else if (face === "South") {
          newQuarterState = { "float_fc:bottom_quarter_1": true };
        } else if (face === "Down") {
          newQuarterState = { "float_fc:top_quarter_4": true };
        }
      } else if (cardinalDirection === "south") {
        if (face === "North") {
          newQuarterState = { "float_fc:bottom_quarter_3": true };
        } else if (face === "West") {
          newQuarterState = { "float_fc:bottom_quarter_3": true };
        } else if (face === "East") {
          newQuarterState = { "float_fc:bottom_quarter_2": true };
        } else if (face === "South") {
          newQuarterState = { "float_fc:bottom_quarter_1": true };
        } else if (face === "Down") {
          newQuarterState = { "float_fc:top_quarter_4": true };
        }
      } else if (cardinalDirection === "east") {
        if (face === "North") {
          newQuarterState = { "float_fc:bottom_quarter_3": true };
        } else if (face === "West") {
          newQuarterState = { "float_fc:bottom_quarter_3": true };
        } else if (face === "East") {
          newQuarterState = { "float_fc:bottom_quarter_2": true };
        } else if (face === "South") {
          newQuarterState = { "float_fc:bottom_quarter_1": true };
        } else if (face === "Down") {
          newQuarterState = { "float_fc:top_quarter_4": true };
        }
      } else if (cardinalDirection === "west") {
        if (face === "North") {
          newQuarterState = { "float_fc:bottom_quarter_3": true };
        } else if (face === "West") {
          newQuarterState = { "float_fc:bottom_quarter_3": true };
        } else if (face === "East") {
          newQuarterState = { "float_fc:bottom_quarter_2": true };
        } else if (face === "South") {
          newQuarterState = { "float_fc:bottom_quarter_1": true };
        } else if (face === "Down") {
          newQuarterState = { "float_fc:top_quarter_4": true };
        }
      }
    } else if (updatedState["float_fc:bottom_quarter_3"]) {
      if (cardinalDirection === "north") {
        if (face === "North") {
          newQuarterState = { "float_fc:bottom_quarter_4": true };
        } else if (face === "West") {
          newQuarterState = { "float_fc:bottom_quarter_2": true };
        } else if (face === "East") {
          newQuarterState = { "float_fc:bottom_quarter_4": true };
        } else if (face === "South") {
          newQuarterState = { "float_fc:bottom_quarter_2": true };
        } else if (face === "Down") {
          newQuarterState = { "float_fc:top_quarter_3": true };
        }
      } else if (cardinalDirection === "south") {
        if (face === "North") {
          newQuarterState = { "float_fc:bottom_quarter_4": true };
        } else if (face === "West") {
          newQuarterState = { "float_fc:bottom_quarter_2": true };
        } else if (face === "East") {
          newQuarterState = { "float_fc:bottom_quarter_4": true };
        } else if (face === "South") {
          newQuarterState = { "float_fc:bottom_quarter_2": true };
        } else if (face === "Down") {
          newQuarterState = { "float_fc:top_quarter_3": true };
        }
      } else if (cardinalDirection === "east") {
        if (face === "North") {
          newQuarterState = { "float_fc:bottom_quarter_4": true };
        } else if (face === "West") {
          newQuarterState = { "float_fc:bottom_quarter_2": true };
        } else if (face === "East") {
          newQuarterState = { "float_fc:bottom_quarter_4": true };
        } else if (face === "South") {
          newQuarterState = { "float_fc:bottom_quarter_2": true };
        } else if (face === "Down") {
          newQuarterState = { "float_fc:top_quarter_3": true };
        }
      } else if (cardinalDirection === "west") {
        if (face === "North") {
          newQuarterState = { "float_fc:bottom_quarter_4": true };
        } else if (face === "West") {
          newQuarterState = { "float_fc:bottom_quarter_2": true };
        } else if (face === "East") {
          newQuarterState = { "float_fc:bottom_quarter_4": true };
        } else if (face === "South") {
          newQuarterState = { "float_fc:bottom_quarter_2": true };
        } else if (face === "Down") {
          newQuarterState = { "float_fc:top_quarter_3": true };
        }
      }
    } else if (updatedState["float_fc:bottom_quarter_2"]) {
      if (cardinalDirection === "north") {
        if (face === "North") {
          newQuarterState = { "float_fc:bottom_quarter_3": true };
        } else if (face === "West") {
          newQuarterState = { "float_fc:bottom_quarter_2": true };
        } else if (face === "East") {
          newQuarterState = { "float_fc:bottom_quarter_1": true };
        } else if (face === "South") {
          newQuarterState = { "float_fc:bottom_quarter_4": true };
        } else if (face === "Down") {
          newQuarterState = { "float_fc:top_quarter_2": true };
        }
      } else if (cardinalDirection === "south") {
        if (face === "North") {
          newQuarterState = { "float_fc:bottom_quarter_3": true };
        } else if (face === "West") {
          newQuarterState = { "float_fc:bottom_quarter_2": true };
        } else if (face === "East") {
          newQuarterState = { "float_fc:bottom_quarter_1": true };
        } else if (face === "South") {
          newQuarterState = { "float_fc:bottom_quarter_4": true };
        } else if (face === "Down") {
          newQuarterState = { "float_fc:top_quarter_2": true };
        }
      } else if (cardinalDirection === "east") {
        if (face === "North") {
          newQuarterState = { "float_fc:bottom_quarter_3": true };
        } else if (face === "West") {
          newQuarterState = { "float_fc:bottom_quarter_2": true };
        } else if (face === "East") {
          newQuarterState = { "float_fc:bottom_quarter_1": true };
        } else if (face === "South") {
          newQuarterState = { "float_fc:bottom_quarter_4": true };
        } else if (face === "Down") {
          newQuarterState = { "float_fc:top_quarter_2": true };
        }
      } else if (cardinalDirection === "west") {
        if (face === "North") {
          newQuarterState = { "float_fc:bottom_quarter_3": true };
        } else if (face === "West") {
          newQuarterState = { "float_fc:bottom_quarter_2": true };
        } else if (face === "East") {
          newQuarterState = { "float_fc:bottom_quarter_1": true };
        } else if (face === "South") {
          newQuarterState = { "float_fc:bottom_quarter_4": true };
        } else if (face === "Down") {
          newQuarterState = { "float_fc:top_quarter_2": true };
        }
      }
    } else if (updatedState["float_fc:bottom_quarter_1"]) {
      if (cardinalDirection === "north") {
        if (face === "North") {
          newQuarterState = { "float_fc:bottom_quarter_4": true };
        } else if (face === "West") {
          newQuarterState = { "float_fc:bottom_quarter_2": true };
        } else if (face === "East") {
          newQuarterState = { "float_fc:bottom_quarter_3": true };
        } else if (face === "South") {
          newQuarterState = { "float_fc:bottom_quarter_4": true };
        } else if (face === "Down") {
          newQuarterState = { "float_fc:top_quarter_1": true };
        }
      } else if (cardinalDirection === "south") {
        if (face === "North") {
          newQuarterState = { "float_fc:bottom_quarter_4": true };
        } else if (face === "West") {
          newQuarterState = { "float_fc:bottom_quarter_2": true };
        } else if (face === "East") {
          newQuarterState = { "float_fc:bottom_quarter_3": true };
        } else if (face === "South") {
          newQuarterState = { "float_fc:bottom_quarter_4": true };
        } else if (face === "Down") {
          newQuarterState = { "float_fc:top_quarter_1": true };
        }
      } else if (cardinalDirection === "east") {
        if (face === "North") {
          newQuarterState = { "float_fc:bottom_quarter_4": true };
        } else if (face === "West") {
          newQuarterState = { "float_fc:bottom_quarter_2": true };
        } else if (face === "East") {
          newQuarterState = { "float_fc:bottom_quarter_3": true };
        } else if (face === "South") {
          newQuarterState = { "float_fc:bottom_quarter_4": true };
        } else if (face === "Down") {
          newQuarterState = { "float_fc:top_quarter_1": true };
        }
      } else if (cardinalDirection === "west") {
        if (face === "North") {
          newQuarterState = { "float_fc:bottom_quarter_4": true };
        } else if (face === "West") {
          newQuarterState = { "float_fc:bottom_quarter_2": true };
        } else if (face === "East") {
          newQuarterState = { "float_fc:bottom_quarter_3": true };
        } else if (face === "South") {
          newQuarterState = { "float_fc:bottom_quarter_4": true };
        } else if (face === "Down") {
          newQuarterState = { "float_fc:top_quarter_1": true };
        }
      }
    } else if (updatedState["float_fc:top_quarter_4"]) {
      if (cardinalDirection === "north") {
        if (face === "North") {
          newQuarterState = { "float_fc:top_quarter_3": true };
        } else if (face === "West") {
          newQuarterState = { "float_fc:top_quarter_3": true };
        } else if (face === "East") {
          newQuarterState = { "float_fc:top_quarter_2": true };
        } else if (face === "South") {
          newQuarterState = { "float_fc:top_quarter_1": true };
        } else if (face === "Up") {
          newQuarterState = { "float_fc:bottom_quarter_4": true };
        }
      } else if (cardinalDirection === "south") {
        if (face === "North") {
          newQuarterState = { "float_fc:top_quarter_3": true };
        } else if (face === "West") {
          newQuarterState = { "float_fc:top_quarter_3": true };
        } else if (face === "East") {
          newQuarterState = { "float_fc:top_quarter_2": true };
        } else if (face === "South") {
          newQuarterState = { "float_fc:top_quarter_1": true };
        } else if (face === "Up") {
          newQuarterState = { "float_fc:bottom_quarter_4": true };
        }
      } else if (cardinalDirection === "east") {
        if (face === "North") {
          newQuarterState = { "float_fc:top_quarter_3": true };
        } else if (face === "West") {
          newQuarterState = { "float_fc:top_quarter_3": true };
        } else if (face === "East") {
          newQuarterState = { "float_fc:top_quarter_2": true };
        } else if (face === "South") {
          newQuarterState = { "float_fc:top_quarter_1": true };
        } else if (face === "Up") {
          newQuarterState = { "float_fc:bottom_quarter_4": true };
        }
      } else if (cardinalDirection === "west") {
        if (face === "North") {
          newQuarterState = { "float_fc:top_quarter_3": true };
        } else if (face === "West") {
          newQuarterState = { "float_fc:top_quarter_3": true };
        } else if (face === "East") {
          newQuarterState = { "float_fc:top_quarter_2": true };
        } else if (face === "South") {
          newQuarterState = { "float_fc:top_quarter_1": true };
        } else if (face === "Up") {
          newQuarterState = { "float_fc:bottom_quarter_4": true };
        }
      }
    } else if (updatedState["float_fc:top_quarter_3"]) {
      if (cardinalDirection === "north") {
        if (face === "North") {
          newQuarterState = { "float_fc:top_quarter_4": true };
        } else if (face === "West") {
          newQuarterState = { "float_fc:top_quarter_2": true };
        } else if (face === "East") {
          newQuarterState = { "float_fc:top_quarter_4": true };
        } else if (face === "South") {
          newQuarterState = { "float_fc:top_quarter_2": true };
        } else if (face === "Up") {
          newQuarterState = { "float_fc:bottom_quarter_3": true };
        }
      } else if (cardinalDirection === "south") {
        if (face === "North") {
          newQuarterState = { "float_fc:top_quarter_4": true };
        } else if (face === "West") {
          newQuarterState = { "float_fc:top_quarter_2": true };
        } else if (face === "East") {
          newQuarterState = { "float_fc:top_quarter_4": true };
        } else if (face === "South") {
          newQuarterState = { "float_fc:top_quarter_2": true };
        } else if (face === "Up") {
          newQuarterState = { "float_fc:bottom_quarter_3": true };
        }
      } else if (cardinalDirection === "east") {
        if (face === "North") {
          newQuarterState = { "float_fc:top_quarter_4": true };
        } else if (face === "West") {
          newQuarterState = { "float_fc:top_quarter_2": true };
        } else if (face === "East") {
          newQuarterState = { "float_fc:top_quarter_4": true };
        } else if (face === "South") {
          newQuarterState = { "float_fc:top_quarter_2": true };
        } else if (face === "Up") {
          newQuarterState = { "float_fc:bottom_quarter_3": true };
        }
      } else if (cardinalDirection === "west") {
        if (face === "North") {
          newQuarterState = { "float_fc:top_quarter_4": true };
        } else if (face === "West") {
          newQuarterState = { "float_fc:top_quarter_2": true };
        } else if (face === "East") {
          newQuarterState = { "float_fc:top_quarter_4": true };
        } else if (face === "South") {
          newQuarterState = { "float_fc:top_quarter_2": true };
        } else if (face === "Up") {
          newQuarterState = { "float_fc:bottom_quarter_3": true };
        }
      }
    } else if (updatedState["float_fc:top_quarter_2"]) {
      if (cardinalDirection === "north") {
        if (face === "North") {
          newQuarterState = { "float_fc:top_quarter_3": true };
        } else if (face === "West") {
          newQuarterState = { "float_fc:top_quarter_2": true };
        } else if (face === "East") {
          newQuarterState = { "float_fc:top_quarter_1": true };
        } else if (face === "South") {
          newQuarterState = { "float_fc:top_quarter_4": true };
        } else if (face === "Up") {
          newQuarterState = { "float_fc:bottom_quarter_2": true };
        }
      } else if (cardinalDirection === "south") {
        if (face === "North") {
          newQuarterState = { "float_fc:top_quarter_3": true };
        } else if (face === "West") {
          newQuarterState = { "float_fc:top_quarter_2": true };
        } else if (face === "East") {
          newQuarterState = { "float_fc:top_quarter_1": true };
        } else if (face === "South") {
          newQuarterState = { "float_fc:top_quarter_4": true };
        } else if (face === "Up") {
          newQuarterState = { "float_fc:bottom_quarter_2": true };
        }
      } else if (cardinalDirection === "east") {
        if (face === "North") {
          newQuarterState = { "float_fc:top_quarter_3": true };
        } else if (face === "West") {
          newQuarterState = { "float_fc:top_quarter_2": true };
        } else if (face === "East") {
          newQuarterState = { "float_fc:top_quarter_1": true };
        } else if (face === "South") {
          newQuarterState = { "float_fc:top_quarter_4": true };
        } else if (face === "Up") {
          newQuarterState = { "float_fc:bottom_quarter_2": true };
        }
      } else if (cardinalDirection === "west") {
        if (face === "North") {
          newQuarterState = { "float_fc:top_quarter_3": true };
        } else if (face === "West") {
          newQuarterState = { "float_fc:top_quarter_2": true };
        } else if (face === "East") {
          newQuarterState = { "float_fc:top_quarter_1": true };
        } else if (face === "South") {
          newQuarterState = { "float_fc:top_quarter_4": true };
        } else if (face === "Up") {
          newQuarterState = { "float_fc:bottom_quarter_2": true };
        }
      }
    } else if (updatedState["float_fc:top_quarter_1"]) {
      if (cardinalDirection === "north") {
        if (face === "North") {
          newQuarterState = { "float_fc:top_quarter_4": true };
        } else if (face === "West") {
          newQuarterState = { "float_fc:top_quarter_2": true };
        } else if (face === "East") {
          newQuarterState = { "float_fc:top_quarter_3": true };
        } else if (face === "South") {
          newQuarterState = { "float_fc:top_quarter_4": true };
        } else if (face === "Up") {
          newQuarterState = { "float_fc:bottom_quarter_1": true };
        }
      } else if (cardinalDirection === "south") {
        if (face === "North") {
          newQuarterState = { "float_fc:top_quarter_4": true };
        } else if (face === "West") {
          newQuarterState = { "float_fc:top_quarter_2": true };
        } else if (face === "East") {
          newQuarterState = { "float_fc:top_quarter_3": true };
        } else if (face === "South") {
          newQuarterState = { "float_fc:top_quarter_4": true };
        } else if (face === "Up") {
          newQuarterState = { "float_fc:bottom_quarter_1": true };
        }
      } else if (cardinalDirection === "east") {
        if (face === "North") {
          newQuarterState = { "float_fc:top_quarter_4": true };
        } else if (face === "West") {
          newQuarterState = { "float_fc:top_quarter_2": true };
        } else if (face === "East") {
          newQuarterState = { "float_fc:top_quarter_3": true };
        } else if (face === "South") {
          newQuarterState = { "float_fc:top_quarter_4": true };
        } else if (face === "Up") {
          newQuarterState = { "float_fc:bottom_quarter_1": true };
        }
      } else if (cardinalDirection === "west") {
        if (face === "North") {
          newQuarterState = { "float_fc:top_quarter_4": true };
        } else if (face === "West") {
          newQuarterState = { "float_fc:top_quarter_2": true };
        } else if (face === "East") {
          newQuarterState = { "float_fc:top_quarter_3": true };
        } else if (face === "South") {
          newQuarterState = { "float_fc:top_quarter_4": true };
        } else if (face === "Up") {
          newQuarterState = { "float_fc:bottom_quarter_1": true };
        }
      }
    }

    // Calculate the new block's location based on the face direction
    const newBlockLocation = {
      x: block.location.x + (face === "East" ? 1 : face === "West" ? -1 : 0),
      y: block.location.y + (face === "Up" ? 1 : face === "Down" ? -1 : 0),
      z: block.location.z + (face === "South" ? 1 : face === "North" ? -1 : 0),
    };

    // Check if a quarter block already exists at the calculated location
    const newBlock = block.dimension.getBlock(newBlockLocation);
    if (newBlock.typeId === block.typeId) {
      // If a quarter block exists, merge the newQuarterState with the existing block's states
      const existingStates = newBlock.permutation.getAllStates();
      const mergedStates = { ...existingStates, ...newQuarterState };
      newBlock.setPermutation(BlockPermutation.resolve(block.typeId, mergedStates));
    } else {
      // If no quarter block exists, place a new quarter block at the calculated location
      newBlock.setType(block.typeId);

      // Inherit the cardinal direction from the original block

      // If the updatedState was bottom_quarter_1 and it has changed, set it to false
      if (newQuarterState["float_fc:bottom_quarter_1"] === true) {
        newBlock.setPermutation(BlockPermutation.resolve(block.typeId, newQuarterState));
      } else {
        newQuarterState["float_fc:bottom_quarter_1"] = false;
        newBlock.setPermutation(BlockPermutation.resolve(block.typeId, newQuarterState));
      }
    }
    return;
  }

  // Update the target block's permutation to reflect the new quarter placement
  for (const [key, value] of Object.entries(updatedState)) {
    targetBlock.setPermutation(targetBlock.permutation.withState(key, value));
  }
}

function placeQuarter(quarterBlock, FaceLocation, face, player, permutationToPlace) {
  const updatedPermutation = permutationToPlace.withState("float_fc:bottom_quarter_1", false);

  // Retrieve the cardinal direction from dynamic properties
  const blockLocation = quarterBlock.location;
  const dynamicKey = `float_fc:dir_${blockLocation.x}_${blockLocation.y}_${blockLocation.z}`;
  const dynamicProperties = world.getDynamicProperty(dynamicKey);
  const cardinalDirection = dynamicProperties ?? "north";

  const block = quarterBlock.dimension.getBlock(quarterBlock.location);

  const relativeX = FaceLocation.x - Math.floor(FaceLocation.x);
  const relativeZ = FaceLocation.z - Math.floor(FaceLocation.z);
  const isBottomHalf = FaceLocation.y - Math.floor(FaceLocation.y) < 0.5;

  let newState = {};

  //console.error("§1Cardinal direction: " + cardinalDirection);
  //console.error("§2face: " + face);

  // Determine the correct quarter to place based on the face and cardinal direction
  // NOTE - ALL CARDINAL DIRECTIONS ARE THE SAME faces with new dynamic properties
  if (isBottomHalf) {
    if (face === "Up") {
      newState =
        relativeX < 0.5 && relativeZ < 0.5
          ? { "float_fc:bottom_quarter_1": true }
          : relativeX >= 0.5 && relativeZ < 0.5
          ? { "float_fc:bottom_quarter_2": true }
          : relativeX < 0.5 && relativeZ >= 0.5
          ? { "float_fc:bottom_quarter_4": true }
          : { "float_fc:bottom_quarter_3": true };
    } else if (face === "Down") {
      newState =
        relativeX < 0.5 && relativeZ < 0.5
          ? { "float_fc:top_quarter_1": true }
          : relativeX >= 0.5 && relativeZ < 0.5
          ? { "float_fc:top_quarter_2": true }
          : relativeX < 0.5 && relativeZ >= 0.5
          ? { "float_fc:top_quarter_4": true }
          : { "float_fc:top_quarter_3": true };
    } else if (face === "North") {
      newState = relativeX < 0.5 ? { "float_fc:bottom_quarter_4": true } : { "float_fc:bottom_quarter_3": true };
    } else if (face === "South") {
      newState = relativeX < 0.5 ? { "float_fc:bottom_quarter_1": true } : { "float_fc:bottom_quarter_2": true };
    } else if (face === "East") {
      newState = relativeZ < 0.5 ? { "float_fc:bottom_quarter_1": true } : { "float_fc:bottom_quarter_2": true };
    } else if (face === "West") {
      newState = relativeZ < 0.5 ? { "float_fc:bottom_quarter_2": true } : { "float_fc:bottom_quarter_1": true };
    }
  } else {
    if (face === "North") {
      newState = relativeX < 0.5 ? { "float_fc:top_quarter_4": true } : { "float_fc:top_quarter_3": true };
    } else if (face === "South") {
      newState = relativeX < 0.5 ? { "float_fc:top_quarter_1": true } : { "float_fc:top_quarter_2": true };
    } else if (face === "East") {
      newState = relativeZ < 0.5 ? { "float_fc:top_quarter_1": true } : { "float_fc:top_quarter_4": true };
    } else if (face === "West") {
      newState = relativeZ < 0.5 ? { "float_fc:top_quarter_2": true } : { "float_fc:top_quarter_3": true };
    }
  }

  if (Object.keys(newState).length === 0) {
    player.sendMessage("§cDo not sneak while placing a Quarter Plank ontop/bottom of an existing Quarter Plank.");
    block.setType(permutationToPlace.type.id); // Set block to the quarter plank we are placing
    const defaultPermutation = BlockPermutation.resolve(block.typeId, {
      "float_fc:bottom_quarter_1": true,
      "float_fc:bottom_quarter_2": false,
      "float_fc:bottom_quarter_3": false,
      "float_fc:bottom_quarter_4": false,
      "float_fc:top_quarter_1": false,
      "float_fc:top_quarter_2": false,
      "float_fc:top_quarter_3": false,
      "float_fc:top_quarter_4": false,
    });
    block.setPermutation(defaultPermutation);
    return;
  }
  const finalPermutation = updatedPermutation.withState(Object.keys(newState)[0], Object.values(newState)[0]);
  system.run(() => {
    quarterBlock.dimension.playSound("place.wood", quarterBlock.location);
  });
  // Set the new state on the block
  system.run(() => {
    block.setPermutation(finalPermutation);
  });
}

function destroyQuarter(quarterBlock, FaceLocation, face, player, destroyedBlockPermutation) {
  // Retrieve the current permutation of the block
  const currentPermutation = destroyedBlockPermutation;

  // Determine the relative position of the interaction
  const relativeX = FaceLocation.x - Math.floor(FaceLocation.x);
  const relativeZ = FaceLocation.z - Math.floor(FaceLocation.z);
  let isBottomHalf = FaceLocation.y - Math.floor(FaceLocation.y) < 0.5;

  // Check if the interaction is on a whole block face
  const isTopBottomWholeBlockFace = FaceLocation.y % 1 === 0;

  // Check if the interaction is on the side of a whole block
  const isSideOfWholeBlock = FaceLocation.x % 1 === 0 || FaceLocation.z % 1 === 0;

  // Get the cardinal direction of the block
  const blockLocation = quarterBlock.location;
  const dynamicKey = `float_fc:dir_${blockLocation.x}_${blockLocation.y}_${blockLocation.z}`;
  const dynamicProperties = world.getDynamicProperty(dynamicKey);
  const cardinalDirection = dynamicProperties ?? "north";

  let quarterToRemove = null;
  //console.error("Cardinal direction: " + cardinalDirection);
  //console.error("face: " + face);
  //console.error("Relative X: " + relativeX);
  //console.error("Relative Z: " + relativeZ);
  //console.error(isBottomHalf ? "Bottom half" : "Top half");
  //console.error(isSideOfWholeBlock ? "Side of whole block" : "Not side of whole block");

  // If interacting with a whole block face, always remove a top quarter
  if (isTopBottomWholeBlockFace) {
    //console.error("Interaction on a whole block face, removing a top quarter.");
    isBottomHalf = false; // Force to top half
  }

  // Determine which quarter to remove based on the face, cardinal direction, and relative face locations
  if (isTopBottomWholeBlockFace) {
    if (face === "Up") {
      // If interacting with a whole block face, calculate the location on the face using relativeX and relativeZ
      if (relativeX < 0.5 && relativeZ < 0.5) {
        quarterToRemove = "float_fc:top_quarter_1";
      } else if (relativeX >= 0.5 && relativeZ < 0.5) {
        quarterToRemove = "float_fc:top_quarter_2";
      } else if (relativeX < 0.5 && relativeZ >= 0.5) {
        quarterToRemove = "float_fc:top_quarter_4";
      } else {
        quarterToRemove = "float_fc:top_quarter_3";
      }
    } else if (face === "Down") {
      if (relativeX < 0.5 && relativeZ < 0.5) {
        quarterToRemove = "float_fc:bottom_quarter_1";
      } else if (relativeX >= 0.5 && relativeZ < 0.5) {
        quarterToRemove = "float_fc:bottom_quarter_2";
      } else if (relativeX < 0.5 && relativeZ >= 0.5) {
        quarterToRemove = "float_fc:bottom_quarter_4";
      } else {
        quarterToRemove = "float_fc:bottom_quarter_3";
      }
    }
  } else if (isSideOfWholeBlock) {
    // If interacting with the side of a whole block

    quarterToRemove =
      face === "East"
        ? relativeZ >= 0.5
          ? isBottomHalf
            ? "float_fc:bottom_quarter_3"
            : "float_fc:top_quarter_3"
          : isBottomHalf
          ? "float_fc:bottom_quarter_2"
          : "float_fc:top_quarter_2"
        : face === "West"
        ? relativeZ < 0.5
          ? isBottomHalf
            ? "float_fc:bottom_quarter_1"
            : "float_fc:top_quarter_1"
          : isBottomHalf
          ? "float_fc:bottom_quarter_4"
          : "float_fc:top_quarter_4"
        : face === "North"
        ? relativeX < 0.5
          ? isBottomHalf
            ? "float_fc:bottom_quarter_1"
            : "float_fc:top_quarter_1"
          : isBottomHalf
          ? "float_fc:bottom_quarter_2"
          : "float_fc:top_quarter_2"
        : face === "South"
        ? relativeX >= 0.5
          ? isBottomHalf
            ? "float_fc:bottom_quarter_3"
            : "float_fc:top_quarter_3"
          : isBottomHalf
          ? "float_fc:bottom_quarter_4"
          : "float_fc:top_quarter_4"
        : null;
  } else {
    // If interacting with a specific quarter

    if (face === "Up") {
      if (relativeX < 0.5 && relativeZ < 0.5) {
        quarterToRemove = "float_fc:bottom_quarter_1";
      } else if (relativeX >= 0.5 && relativeZ < 0.5) {
        quarterToRemove = "float_fc:bottom_quarter_2";
      } else if (relativeX < 0.5 && relativeZ >= 0.5) {
        quarterToRemove = "float_fc:bottom_quarter_4";
      } else {
        quarterToRemove = "float_fc:bottom_quarter_3";
      }
    } else if (face === "Down") {
      //console.error("running down");
      if (relativeX < 0.5 && relativeZ < 0.5) {
        quarterToRemove = "float_fc:top_quarter_1";
      } else if (relativeX >= 0.5 && relativeZ < 0.5) {
        quarterToRemove = "float_fc:top_quarter_2";
      } else if (relativeX < 0.5 && relativeZ >= 0.5) {
        quarterToRemove = "float_fc:top_quarter_4";
      } else {
        quarterToRemove = "float_fc:top_quarter_3";
      }
    } else {
      quarterToRemove =
        face === "North"
          ? relativeX < 0.5
            ? isBottomHalf
              ? "float_fc:bottom_quarter_4"
              : "float_fc:top_quarter_4"
            : isBottomHalf
            ? "float_fc:bottom_quarter_3"
            : "float_fc:top_quarter_3"
          : face === "South"
          ? relativeX >= 0.5
            ? isBottomHalf
              ? "float_fc:bottom_quarter_2"
              : "float_fc:top_quarter_2"
            : isBottomHalf
            ? "float_fc:bottom_quarter_1"
            : "float_fc:top_quarter_1"
          : face === "East"
          ? relativeZ >= 0.5
            ? isBottomHalf
              ? "float_fc:bottom_quarter_4"
              : "float_fc:top_quarter_4"
            : isBottomHalf
            ? "float_fc:bottom_quarter_1"
            : "float_fc:top_quarter_1"
          : face === "West"
          ? relativeZ < 0.5
            ? isBottomHalf
              ? "float_fc:bottom_quarter_2"
              : "float_fc:top_quarter_2"
            : isBottomHalf
            ? "float_fc:bottom_quarter_3"
            : "float_fc:top_quarter_3"
          : quarterToRemove;
    }
  }

  if (quarterToRemove && quarterBlock.typeId !== "minecraft:air") {
    //console.error("Removing quarter: " + quarterToRemove);
    // Update the permutation to remove the specified quarter
    const updatedPermutation = currentPermutation.withState(quarterToRemove, false);

    // Set the updated permutation on the block
    quarterBlock.setPermutation(updatedPermutation);

    // Check if all quarters are removed, and if so, destroy the block
    const allQuarters = [
      "float_fc:bottom_quarter_1",
      "float_fc:bottom_quarter_2",
      "float_fc:bottom_quarter_3",
      "float_fc:bottom_quarter_4",
      "float_fc:top_quarter_1",
      "float_fc:top_quarter_2",
      "float_fc:top_quarter_3",
      "float_fc:top_quarter_4",
    ];
    const hasAnyQuarter = allQuarters.some((quarter) => updatedPermutation.getState(quarter));
    if (player.getGameMode() !== "creative") {
      const itemStack = new ItemStack(quarterBlock.typeId, 1);
      quarterBlock.dimension.spawnItem(itemStack, quarterBlock.location);
    }
    if (!hasAnyQuarter) {
      removeCardinalDirectionDynamic(quarterBlock);
      quarterBlock.setType(BlockTypes.get("minecraft:air"));
    }
    quarterBlock.dimension.playSound("dig.wood", quarterBlock.location);
  }
}

function storeCardinalDirectionOnPlace(block, player) {
  //console.error("Storing cardinal direction on place");
  const rotation = ((player.getRotation().y % 360) + 360) % 360;
  let cardinalDirection;
  if (rotation >= 315 || rotation < 45) {
    cardinalDirection = "south";
  } else if (rotation >= 45 && rotation < 135) {
    cardinalDirection = "west";
  } else if (rotation >= 135 && rotation < 225) {
    cardinalDirection = "north";
  } else {
    cardinalDirection = "east";
  }

  const key = `float_fc:dir_${block.location.x}_${block.location.y}_${block.location.z}`;
  world.setDynamicProperty(key, cardinalDirection);
  //console.error(`Stored dynamic property: ${key} = ${cardinalDirection}`);
}

function removeCardinalDirectionDynamic(block) {
  const key = `float_fc:dir_:${block.location.x},${block.location.y},${block.location.z}`;
  world.setDynamicProperty(key, null);
  //console.error(`Removed cardinal direction dynamic property for ${key}`);
}

function stairCheck(stairBlock) {
  if (isCustomStairs(stairBlock)) {
    updateStair(stairBlock);
  }
  if (isCustomStairs(stairBlock.north())) {
    updateStair(stairBlock.north());
  }
  if (isCustomStairs(stairBlock.south())) {
    updateStair(stairBlock.south());
  }
  if (isCustomStairs(stairBlock.east())) {
    updateStair(stairBlock.east());
  }
  if (isCustomStairs(stairBlock.west())) {
    updateStair(stairBlock.west());
  }
}

function pathCheck(pathBlock) {
  const isWide = isCustomPathWide(pathBlock);
  const isNormal = isCustomPath(pathBlock);

  if (isWide || isNormal) {
    updatePath(pathBlock);
  }

  if (isWide) {
    if (isCustomPathWide(pathBlock.north())) {
      updatePath(pathBlock.north());
    }
    if (isCustomPathWide(pathBlock.south())) {
      updatePath(pathBlock.south());
    }
    if (isCustomPathWide(pathBlock.east())) {
      updatePath(pathBlock.east());
    }
    if (isCustomPathWide(pathBlock.west())) {
      updatePath(pathBlock.west());
    }
  } else if (isNormal) {
    if (isCustomPath(pathBlock.north())) {
      updatePath(pathBlock.north());
    }
    if (isCustomPath(pathBlock.south())) {
      updatePath(pathBlock.south());
    }
    if (isCustomPath(pathBlock.east())) {
      updatePath(pathBlock.east());
    }
    if (isCustomPath(pathBlock.west())) {
      updatePath(pathBlock.west());
    }
  }
}

function palisadeCheck(palisadeBlock) {
  if (isCustomPalisade(palisadeBlock.above())) {
    updatePalisade(palisadeBlock.above());
  }
  if (isCustomPalisade(palisadeBlock.below())) {
    updatePalisade(palisadeBlock.below());
  }
  if (isCustomPalisade(palisadeBlock)) {
    updatePalisade(palisadeBlock);
  }
}

function palisadeShear(palisadeBlock, player) {
  if (isCustomPalisade(palisadeBlock)) {
    shearPalisade(palisadeBlock, player);
  }
}

function isCustomPath(testBlock) {
  if (testBlock != undefined && testBlock.hasTag("custom_path")) {
    return true;
  }
  return false;
}

function isCustomPalisade(testBlock) {
  if (testBlock != undefined && testBlock.hasTag("custom_palisade")) {
    return true;
  }
  return false;
}

function isCustomPathWide(testBlock) {
  if (testBlock != undefined && testBlock.hasTag("custom_path_wide")) {
    return true;
  }
  return false;
}

function isCustomStairs(testBlock) {
  if (testBlock != undefined && (testBlock.hasTag("custom_stairs_up") || testBlock.hasTag("custom_stairs_down"))) {
    return true;
  }
  return false;
}

function handleAfterPlaced(event) {
  try {
    if (event.block.typeId == "float_fc:juicer" && event.player && event.player.hasTag("juicer_tutorial")) {
      event.block.dimension.runCommand(
        `summon float_fc:chopped_fruit_want_particle ${event.block.center().x} ${event.block.center().y + 0.5} ${
          event.block.center().z
        }`
      );
    } else if (
      event.block.typeId == "float_fc:boiling_pot" &&
      event.player &&
      event.player.hasTag("boiling_pot_tutorial")
    ) {
      event.block.dimension.runCommand(
        `summon float_fc:chopped_fruit_want_particle ${event.block.center().x} ${event.block.center().y + 0.5} ${
          event.block.center().z
        }`
      );
    } else if (
      event.block.typeId == "float_fc:slushie_maker" &&
      event.player &&
      event.player.hasTag("slushie_tutorial_glass")
    ) {
      event.block.dimension.runCommand(
        `summon float_fc:juice_want_particle ${event.block.center().x} ${event.block.center().y + 0.5} ${
          event.block.center().z
        }`
      );
    } else if (
      event.block.typeId == "float_fc:chopping_board" &&
      event.player &&
      event.player.hasTag("chopping_tutorial")
    ) {
      event.block.dimension.runCommand(
        `summon float_fc:fruit_want_particle ${event.block.center().x} ${event.block.center().y + 0.5} ${
          event.block.center().z
        }`
      );
    } else {
      checkForSapling(event);
      updateBlocksCheck(event);
    }
  } catch (e) {
    //return;
  }
}
world.afterEvents.playerPlaceBlock.subscribe(handleAfterPlaced);

var saplingsLock = false;
var miniChunkSaplings = new Map();
async function pushToSaplingQueue(event) {
  while (saplingsLock) {
    await system.waitTicks(5);
  }
  saplingsLock = true;
  const chunkSize = 512;
  var loc, id, currentQueue;
  try {
    loc = event.block.location;
    id =
      "" +
      Math.floor(loc.x / chunkSize) * chunkSize +
      "_" +
      Math.floor(loc.y / chunkSize) * chunkSize +
      "_" +
      Math.floor(loc.z / chunkSize) * chunkSize;
    currentQueue = miniChunkSaplings.get(id);
    if (currentQueue == undefined) {
      currentQueue = Array();
    }
    currentQueue.unshift(event);
    miniChunkSaplings.set(id, currentQueue);
  } catch (e) {
  } finally {
    loc = id = currentQueue = undefined;
    saplingsLock = false;
  }
}
async function processSaplingQueue() {
  var done, item, newMap;
  while (saplingsLock) {
    await system.waitTicks(Math.floor(Math.random() * 20));
  }
  saplingsLock = true;
  try {
    newMap = new Map();
    done = true;
    function processMiniChunk(value, key, map) {
      done = !done || value.length > 1;
      item = value.pop();
      if (item) {
        handleSaplingQueueItem(item);
      }
      if (value.length > 0) {
        newMap.set(key, value);
      }
    }
    miniChunkSaplings.forEach(processMiniChunk);
    miniChunkSaplings = newMap;
  } finally {
    saplingsLock = false;
    try {
      await system.waitTicks(5);
      if (!done) {
        while (saplingsLock) {
          await system.waitTicks(Math.floor(Math.random() * 20));
        }
        system.runTimeout(processSaplingQueue, 20);
      }
    } catch (e) {}
  }
}

var commandLock = false;
var miniChunkCommands = new Map();
async function pushToCommandQueue(command, loc) {
  while (commandLock) {
    await system.waitTicks(5);
  }
  commandLock = true;
  const chunkSize = 512;
  var id, currentQueue;
  try {
    id =
      "" +
      Math.floor(loc.x / chunkSize) * chunkSize +
      "_" +
      Math.floor(loc.y / chunkSize) * chunkSize +
      "_" +
      Math.floor(loc.z / chunkSize) * chunkSize;
    currentQueue = miniChunkCommands.get(id);
    if (currentQueue == undefined) {
      currentQueue = Array();
    }
    currentQueue.push(command);
    miniChunkCommands.set(id, currentQueue);
  } catch (e) {
  } finally {
    id = currentQueue = undefined;
    commandLock = false;
  }
}
async function processCommandQueue() {
  var done, item, newMap;
  while (commandLock) {
    await system.waitTicks(Math.floor(Math.random() * 100));
  }
  commandLock = true;
  try {
    newMap = new Map();
    done = true;
    function processMiniChunk(value, key, map) {
      done = !done || value.length > 1;
      item = value.pop();
      if (item) {
        ow.runCommand(item);
      }
      if (value.length > 0) {
        newMap.set(key, value);
      }
    }
    miniChunkCommands.forEach(processMiniChunk);
    miniChunkCommands = newMap;
  } catch (e) {
  } finally {
    commandLock = false;
    try {
      await system.waitTicks(5);
      if (!done) {
        while (commandLock) {
          await system.waitTicks(Math.floor(Math.random() * 100));
        }
        system.runTimeout(processCommandQueue, 20);
      }
    } catch (e) {}
  }
}
function handleSaplingQueueItem(event) {
  let result = null;

  // Check if there's space above the sapling for the tree to grow
  if (!checkTreeGrowSpace(event.block.location, event.block.dimension)) {
    // No space for the tree to grow, don't grow the tree
    return;
  }

  if (smallSaplings.has(event.block.typeId)) {
    result = growTreeSmall(event.block.location, event.block.typeId, true, event.block.dimension);
  } else if (fruitSaplings.has(event.block.typeId)) {
    result = growTreeFruit(event.block.location, event.block.typeId, true, event.block.dimension);
  } else if (mediumSaplings.has(event.block.typeId)) {
    result = growTreeMedium(event.block.location, event.block.typeId, true, event.block.dimension);
  } else if (largeSaplings.has(event.block.typeId)) {
    result = growTreeLarge(event.block.location, event.block.typeId, true, event.block.dimension);
  } else if (redwooodSaplings.has(event.block.typeId)) {
    result = growTreeRedwood(event.block.location, event.block.typeId, true, event.block.dimension);
  } else if (sapling_9_11_13.has(event.block.typeId)) {
    result = growTree9_11_13(event.block.location, event.block.typeId, true, event.block.dimension);
  } else if (bonesapling.has(event.block.typeId)) {
    result = growTreeBone(event.block.location, event.block.typeId, true, event.block.dimension);
  } else if (mushroomsapling.has(event.block.typeId)) {
    result = growTreeMushroom(event.block.location, event.block.typeId, true, event.block.dimension);
  } else if (pinesapling.has(event.block.typeId)) {
    result = growTreePine(event.block.location, event.block.typeId, true, event.block.dimension);
  } else if (sapling_15_17_19.has(event.block.typeId)) {
    result = growTree15_17_19(event.block.location, event.block.typeId, true, event.block.dimension);
  } else if (vanilla_cherry.has(event.block.typeId)) {
    result = growTreeGiantCherry(event.block.location, event.block.typeId, true, event.block.dimension);
  } else if (coconutsapling.has(event.block.typeId)) {
    result = growTreeCoconut(event.block.location, event.block.typeId, true, event.block.dimension);
  } else if (avocadoSaplings.has(event.block.typeId)) {
    result = growTreeAvocado(event.block.location, event.block.typeId, true, event.block.dimension);
  } else if (pinkOleanderSaplings.has(event.block.typeId)) {
    result = growTreePinkOleander(event.block.location, event.block.typeId, true, event.block.dimension);
  } else if (sapling_9_9_11_13.has(event.block.typeId)) {
    result = growTree9_9_11_13(event.block.location, event.block.typeId, true, event.block.dimension);
  }
  if (result) {
    pushToCommandQueue(result, event.block.location)
      .then(() => {
        system.runTimeout(processCommandQueue, 800);
      })
      .catch((error) => {});
  }
}

function checkForSapling(event) {
  if (!event) {
    return;
  }

  if (!event.block) {
    // Handle cases where the event is related to an entity spawn
    if (event.cause === "Spawned" && event.entity) {
      // Check if the entity is a temporary sapling
      if (event.entity.typeId.endsWith("_temp")) {
        const saplingType = event.entity.typeId.replace("_temp", "");
        const { x, y, z } = event.entity.location; // Ensure the dimension is valid before proceeding
        if (event.entity && event.entity.dimension) {
          // Check if there's space above the sapling for the tree to grow
          if (!checkTreeGrowSpace(event.entity.location, event.entity.dimension)) {
            return;
          }

          const result = growTreeSmall(event.entity.location, saplingType, false, event.entity.dimension);
          if (result) {
            pushToCommandQueue(result, event.entity.location)
              .then(() => {
                system.runTimeout(processCommandQueue, 800);
              })
              .catch(() => {});
          }
        }
      }
    }
    return;
  }

  if (!event.block.dimension) {
    return;
  }

  if (
    smallSaplings.has(event.block.typeId) ||
    fruitSaplings.has(event.block.typeId) ||
    mediumSaplings.has(event.block.typeId) ||
    largeSaplings.has(event.block.typeId) ||
    redwooodSaplings.has(event.block.typeId) ||
    sapling_9_11_13.has(event.block.typeId) ||
    bonesapling.has(event.block.typeId) ||
    mushroomsapling.has(event.block.typeId) ||
    pinesapling.has(event.block.typeId) ||
    sapling_15_17_19.has(event.block.typeId) ||
    vanilla_cherry.has(event.block.typeId) ||
    avocadoSaplings.has(event.block.typeId) ||
    coconutsapling.has(event.block.typeId)
  ) {
    pushToSaplingQueue(event)
      .then(() => {
        system.runTimeout(processSaplingQueue, 800);
      })
      .catch((error) => {});
  }
}

function getMatchedForestryLogId(brokenblock, logSet) {
  for (const logType of logSet) {
    if (brokenblock.matches(logType)) {
      return logType;
    }
  }
  return null;
}

function getMatchedForestryDoorId(brokenblock, DoorSet) {
  for (const DoorType of DoorSet) {
    if (brokenblock.matches(DoorType)) {
      return DoorType;
    }
  }
  return null;
}

//Fruitshaker trigger
function handleBeforePlayerBreak(event) {
  var matchedLeafType = undefined;
  try {
    //tutorial Particles
    if (event.block.permutation.matches("float_fc:slushie_maker")) {
      event.block.dimension.runCommandAsync("event entity @e[type=float_fc:juice_want_particle] float_fc:kill_entity");
      event.block.dimension.runCommandAsync("event entity @e[type=float_fc:glass_want_particle] float_fc:kill_entity");
    } else if (event.block.permutation.matches("float_fc:juicer")) {
      event.block.dimension.runCommandAsync(
        "event entity @e[type=float_fc:chopped_fruit_want_particle] float_fc:kill_entity"
      );
      event.block.dimension.runCommandAsync("event entity @e[type=float_fc:glass_want_particle] float_fc:kill_entity");
    } else if (event.block.permutation.matches("float_fc:boiling_pot")) {
      event.block.dimension.runCommandAsync(
        "event entity @e[type=float_fc:chopped_fruit_want_particle] float_fc:kill_entity"
      );
      event.block.dimension.runCommandAsync("event entity @e[type=float_fc:glass_want_particle] float_fc:kill_entity");
    } else if (
      event.itemStack != undefined &&
      event.itemStack.typeId == "float_fc:tree_shaker" &&
      getMatchedForestryLogId(event.block.permutation, forestryLogsPlusVanilla)
    ) {
      if (event.player.lastTick11 == undefined || system.currentTick - event.player.lastTick11 > 80) {
        system.run(() => {
          fruitshaker(event.player, event.block.permutation, event.block.location, event.block.typeId);
          handleDurability(event.player, 20);
        });
        event.player.lastTick11 = system.currentTick;
      }
      event.cancel = true;
    } else if (
      //Shearing Leaves
      event.itemStack != undefined &&
      shearTools.has(event.itemStack.typeId) &&
      forestryLeavesPlusVanilla.has(event.block.typeId)
    ) {
      const isForestryLeaf = Array.from(forestryLeavesPlusVanilla).some((leafType) => {
        if (event.block.permutation.matches(leafType)) {
          matchedLeafType = leafType;
          return true;
        }
        return false;
      });
      if (isForestryLeaf) {
        system.run(() => {
          shearLeaf(event.block, event.itemStack.typeId, matchedLeafType);
          handleDurability(event.player, 3);
        });
      }
    } else if (JamJars.has(event.block.typeId)) {
      //takejam
      system.run(() => removejam(event.block, event.block.typeId));
      event.cancel = true;
    }
  } catch (e) {
    return;
  }
}
world.beforeEvents.playerBreakBlock.subscribe(handleBeforePlayerBreak);

function handleAfterPlayerBreak(event) {
  let matchedLogType;
  let matchedDoorType;
  try {
    if (event.itemStackBeforeBreak != undefined && event.itemStackBeforeBreak.typeId == "float_fc:chainsaw") {
      // Chainsaw trigger
      matchedLogType = getMatchedForestryLogId(event.brokenBlockPermutation, forestryLogsPlusVanilla);
      if (matchedLogType) {
        if (getMatchedForestryLogId(event.brokenBlockPermutation, forestryLogs) != null) {
          matchedLogType = matchedLogType.replace("log", "sapling_temp");
          if (matchedLogType == "minecraft:oak_sapling_temp") {
            event.player.dimension.runCommand(
              `event entity @e[type=float_fc:apple_sapling_temp,X=${event.block.location.x},Y=${event.block.location.y},Z=${event.block.location.z}] float_fc:kill_entity`
            );
          } else {
            event.player.dimension.runCommand(
              `event entity @e[type=${matchedLogType},X=${event.block.location.x},Y=${event.block.location.y},Z=${event.block.location.z}] float_fc:kill_entity`
            );
          }
        }
        event.player.playSound("float_fc.chainsaw_chop");
        chainsawtree(event.player, event.brokenBlockPermutation, event.block.location);
        handleDurability(event.player, 25);
      }
    } else if (doorTypes.has(event.block.above().typeId) || doorTypes.has(event.block.below().typeId)) {
      matchedDoorType = getMatchedForestryDoorId(event.brokenBlockPermutation, doorTypes);
      if (doorTypes.has(matchedDoorType)) {
        const upper_door_below = event.block.below().permutation.getState("float_fc:upper_block_bit");
        //door break
        // Remove the block from processedBlocks map
        processedBlocks.delete(`${event.block.location.x},${event.block.location.y},${event.block.location.z}`);
        // Check if the below block is one of the door types and set it to air
        if (doorTypes.has(event.block.below().typeId) && !doorTypes.has(event.block.above().typeId)) {
          event.block.below().setType("minecraft:air");
          processedBlocks.delete(`${event.block.location.x},${event.block.location.y - 1},${event.block.location.z}`);
        } else if (upper_door_below == true && doorTypes.has(event.block.above().typeId)) {
          event.block.above().setType("minecraft:air");
          processedBlocks.delete(`${event.block.location.x},${event.block.location.y + 1},${event.block.location.z}`);
        }
        // Check if the above block is one of the door types and set it to air
        else if (doorTypes.has(event.block.above().typeId) && !doorTypes.has(event.block.below().typeId)) {
          event.block.above().setType("minecraft:air");
          processedBlocks.delete(`${event.block.location.x},${event.block.location.y + 1},${event.block.location.z}`);
        } else if (doorTypes.has(event.block.above().typeId) && doorTypes.has(event.block.below().typeId)) {
          event.block.below().setType("minecraft:air");
          processedBlocks.delete(`${event.block.location.x},${event.block.location.y - 1},${event.block.location.z}`);
        }
      }
    } else {
      updateBlocksCheck(event);
    }
  } catch (e) {
    return;
  }
}

export function handleDurabilitystrip(player, damage) {
  // Skip durability reduction if player is in creative mode
  if (player.getGameMode() === "creative") {
    return;
  }

  const toolType = player.getComponent("equippable")?.getEquipment("Mainhand");
  let damageTotalRemove = damage;
  let actualDurability =
    toolType.getComponent("minecraft:durability").maxDurability - toolType.getComponent("minecraft:durability").damage;
  if (actualDurability > damageTotalRemove) {
    toolType.getComponent("durability").damage = toolType.getComponent("durability").damage + damageTotalRemove;
    player.getComponent("equippable").setEquipment("Mainhand", toolType);
  } else {
    player.runCommand("replaceitem entity @s slot.weapon.mainhand 0 air");
  }
}

export function handleDurability(player, damage) {
  // Skip durability reduction if player is in creative mode
  if (player.getGameMode() === "creative") {
    return;
  }

  const toolType = player.getComponent("equippable")?.getEquipment("Mainhand");
  if (!toolType?.typeId?.startsWith("float_fc:")) {
    return;
  }
  let damageTotalRemove = damage;
  let actualDurability =
    toolType.getComponent("minecraft:durability").maxDurability - toolType.getComponent("minecraft:durability").damage;
  if (actualDurability > damageTotalRemove) {
    toolType.getComponent("durability").damage = toolType.getComponent("durability").damage + damageTotalRemove;
    player.getComponent("equippable").setEquipment("Mainhand", toolType);
  } else {
    player.runCommand("replaceitem entity @s slot.weapon.mainhand 0 air");
  }
}
export function handleDurabilityVanilla(player, damage) {
  // Skip durability reduction if player is in creative mode
  if (player.getGameMode() === "creative") {
    return;
  }

  const toolType = player.getComponent("equippable")?.getEquipment("Mainhand");
  let damageTotalRemove = damage;
  let actualDurability =
    toolType.getComponent("minecraft:durability").maxDurability - toolType.getComponent("minecraft:durability").damage;
  if (actualDurability > damageTotalRemove) {
    toolType.getComponent("durability").damage = toolType.getComponent("durability").damage + damageTotalRemove;
    player.getComponent("equippable").setEquipment("Mainhand", toolType);
  } else {
    player.runCommand("replaceitem entity @s slot.weapon.mainhand 0 air");
  }
}
world.afterEvents.playerBreakBlock.subscribe(handleAfterPlayerBreak);

//Fruit Refinement - Juice Fruit/Chop fruit/Boil Fruit
function handleBeforeItemUse(event) {
  var isForestryChoppedFruit,
    isForestryFruit = undefined;
  try {
    function checkForestryChoppedFruit() {
      if (isForestryChoppedFruit == undefined) {
        isForestryChoppedFruit = forestryChoppedFruitItems.has(event.itemStack.typeId);
      }
      return isForestryChoppedFruit;
    }
    function checkForestryChoppedFruitNoSap() {
      if (isForestryChoppedFruit == undefined) {
        isForestryChoppedFruit = forestryChoppedFruitItemsNoSap.has(event.itemStack.typeId);
      }
      return isForestryChoppedFruit;
    }
    function checkForestryFruit() {
      if (isForestryFruit == undefined) {
        isForestryFruit = forestryFruitItems.has(event.itemStack.typeId);
      }
      return isForestryFruit;
    }
    if (strippingTools.has(event.itemStack.typeId) && forestryLogsPlusVanilla.has(event.block.typeId)) {
      let matchedLogType;
      matchedLogType = getMatchedForestryLogId(event.block.permutation, forestryLogsPlusVanilla);
      if (event.source.lastTick10 == undefined || system.currentTick - event.source.lastTick10 > 5) {
        system.run(() => handleDurabilitystrip(event.source, 2));
        system.run(() => stripLog(event.block, event.itemStack, event.source, matchedLogType));
        event.source.lastTick10 = system.currentTick;
      }
    } else if (
      event.itemStack.typeId == "float_fc:tree_shaker" ||
      event.itemStack.typeId == "float_fc:chainsaw" ||
      event.itemStack.typeId == "float_fc:shear_axe"
    ) {
      //do nothing
    } else if (event.block.typeId == "float_fc:juicer") {
      if (
        event.itemStack.typeId == "minecraft:glass_bottle" &&
        event.block.permutation.getState("float_fc:fill_stage") >= 1
      ) {
        if (event.source.lastTick == undefined || system.currentTick - event.source.lastTick > 5) {
          system.run(() => createJuice(event.block, event.itemStack, event.source));
          event.source.lastTick = system.currentTick;
        }
      } else if (checkForestryChoppedFruitNoSap() && event.block.permutation.getState("float_fc:fill_stage") < 5) {
        if (event.source.lastTick2 == undefined || system.currentTick - event.source.lastTick2 > 5) {
          if (
            (event.itemStack.typeId != "float_fc:chopped_apple_fruit" &&
              event.block.permutation.getState("float_fc:fill_stage") < 5) ||
            (event.itemStack.typeId == "float_fc:chopped_apple_fruit" &&
              event.block.permutation.getState("float_fc:fill_stage") < 4)
          ) {
            system.run(() => juiceFruit(event.block, event.itemStack, event.source));
            event.source.lastTick2 = system.currentTick;
          }
        }
      } else {
        if (event.source.lastTick == undefined || system.currentTick - event.source.lastTick > 5) {
          event.source.sendMessage("§cOnly Chopped Fruit can be juiced");
          event.source.lastTick = system.currentTick;
        }
      }
    } else if (event.block.typeId == "float_fc:slushie_maker") {
      if (
        event.itemStack.typeId == "minecraft:glass_bottle" &&
        event.block.permutation.getState("float_fc:fill_stage") >= 1
      ) {
        if (event.source.lastTick8 == undefined || system.currentTick - event.source.lastTick8 > 5) {
          system.run(() => createSlushie(event.block, event.itemStack, event.source));
          event.source.lastTick8 = system.currentTick;
        }
      } else if (
        forestryJuice.has(event.itemStack.typeId) &&
        event.block.permutation.getState("float_fc:fill_stage") < 4
      ) {
        system.run(() => slushJuice(event.block, event.itemStack, event.source));
      } else if (checkForestryFruit() || checkForestryChoppedFruit()) {
        if (event.source.lastTick == undefined || system.currentTick - event.source.lastTick > 5) {
          event.source.sendMessage("§cOnly Juice can be turned into Slushies");
          event.source.lastTick = system.currentTick;
        }
      }
    } else if (event.block.typeId == "float_fc:boiling_pot") {
      if (
        event.itemStack.typeId == "minecraft:glass_bottle" &&
        event.block.permutation.getState("float_fc:fill_stage") >= 4
      ) {
        if (event.source.lastTick6 == undefined || system.currentTick - event.source.lastTick6 > 5) {
          system.run(() => createJam(event.block, event.itemStack, event.source));
          event.source.lastTick6 = system.currentTick;
        }
      } else if (checkForestryChoppedFruit() && event.block.permutation.getState("float_fc:fill_stage") < 4) {
        system.run(() => boilFruit(event.block, event.itemStack, event.source));
      } else if (checkForestryFruit()) {
        event.source.sendMessage("§cOnly Chopped Fruit (of one type) can be Boiled");
      }
    } else if (event.block.typeId == "float_fc:chopping_board") {
      if (checkForestryFruit() && event.block.permutation.getState("float_fc:chopping") == 0) {
        system.run(() => chopFruit(event.block, event.itemStack, event.source));
      } else if (checkForestryChoppedFruit()) {
        event.source.sendMessage("§cFruit already chopped");
      }
    } else if (event.itemStack.typeId == "minecraft:bone_meal" && allSaplings.has(event.block.typeId)) {
      if (event.source.lastTick10 == undefined || system.currentTick - event.source.lastTick10 > 5) {
        system.run(() => {
          let result;
          result = bonemealSapling(event.block, event.itemStack, event.source);
          if (result) {
            pushToCommandQueue(result, event.block.location)
              .then(() => {
                system.runTimeout(processCommandQueue, 100);
              })
              .catch((error) => {});
          }
        });
        event.source.lastTick10 = system.currentTick;
      }
    } else if (event.itemStack.typeId === "float_fc:pie_slicer" && forestryPies.has(event.block.typeId)) {
      if (event.source.lastTick4 == undefined || system.currentTick - event.source.lastTick4 > 5) {
        system.run(() => slicepie(event.block, event.block.typeId, event.source));
        event.source.lastTick4 = system.currentTick;
      }
    }
  } catch {}
  isForestryChoppedFruit = isForestryFruit = undefined;
}
world.beforeEvents.itemUseOn.subscribe(handleBeforeItemUse);

//Book translate UI
system.afterEvents.scriptEventReceive.subscribe(
  showDialogueOnItemUse({
    EventTypeId: EVENT_ID,
    title: {
      translate: "float_fc:guide.name",
    },
    content: {
      rawtext: [
        { translate: "float_fc:info.part_01", with: ["\n"] },
        { text: "§r\n\n" },
        { translate: "float_fc:info.part_02", with: ["\n"] },
        { text: "§r\n\n" },
        { translate: "float_fc:info.part_03", with: ["\n"] },
        { text: "§r\n\n" },
        { translate: "float_fc:info.part_04", with: ["\n"] },
        { text: "§r\n\n" },
        { translate: "float_fc:info.part_05", with: ["\n"] },
        { text: "§r\n\n" },
        { translate: "float_fc:info.part_06", with: ["\n"] },
        { text: "§r\n\n" },
        { translate: "float_fc:info.part_07", with: ["\n"] },
        { text: "§r\n\n" },
        { translate: "float_fc:info.part_08", with: ["\n"] },
        { text: "§r\n\n" },
        { translate: "float_fc:info.part_09", with: ["\n"] },
        { text: "§r\n\n" },
        { translate: "float_fc:info.part_10", with: ["\n"] },
        { text: "§r\n\n" },
        { translate: "float_fc:info.part_11", with: ["\n"] },
        { text: "§r\n\n" },
        { translate: "float_fc:info.part_12", with: ["\n"] },
        { text: "§r\n\n" },
        { translate: "float_fc:info.part_13", with: ["\n"] },
        { text: "§r\n\n" },
        { translate: "float_fc:info.part_14", with: ["\n"] },
        { text: "§r\n\n" },
        { translate: "float_fc:info.part_15", with: ["\n"] },
        { text: "§r\n\n" },
        { translate: "float_fc:info.part_16", with: ["\n"] },
        { text: "§r\n\n" },
        { translate: "float_fc:info.part_17", with: ["\n"] },
        { text: "§r\n\n" },
        { translate: "float_fc:info.part_18", with: ["\n"] },
        { text: "§r\n\n" },
        { translate: "float_fc:info.part_19", with: ["\n"] },
        { text: "§r\n\n" },
        { translate: "float_fc:info.part_20", with: ["\n"] },
        { text: "§r\n\n" },
        { translate: "float_fc:info.part_21", with: ["\n"] },
        { text: "§r\n\n" },
        { translate: "float_fc:info.part_22", with: ["\n"] },
        { text: "§r\n\n" },
        { translate: "float_fc:info.part_23", with: ["\n"] },
        { text: "§r\n\n" },
        { translate: "float_fc:info.part_24", with: ["\n"] },
        { text: "§r\n\n" },
        { translate: "float_fc:info.part_25", with: ["\n"] },
        { text: "§r\n\n" },
        { translate: "float_fc:info.part_26", with: ["\n"] },
        { text: "§r\n\n" },
        { translate: "float_fc:info.part_27", with: ["\n"] },
        { text: "§r\n\n" },
        { translate: "float_fc:info.part_28", with: ["\n"] },
        { text: "§r\n\n" },
        { translate: "float_fc:info.part_29", with: ["\n"] },
        { text: "§r\n\n" },
        { translate: "float_fc:info.part_30", with: ["\n"] },
        { text: "§r\n\n" },
        { translate: "float_fc:info.part_31", with: ["\n"] },
        { text: "§r\n\n" },
        { translate: "float_fc:info.part_32", with: ["\n"] },
        { text: "§r\n\n" },
        { translate: "float_fc:info.part_33", with: ["\n"] },
        { text: "§r\n\n" },
        { translate: "float_fc:info.part_34", with: ["\n"] },
        { text: "§r\n\n" },
        { translate: "float_fc:info.part_35", with: ["\n"] },
        { text: "§r\n\n" },
        { translate: "float_fc:info.part_36", with: ["\n"] },
        { text: "§r\n\n" },
        { translate: "float_fc:info.part_37", with: ["\n"] },
        { text: "§r\n\n" },
        { translate: "float_fc:info.part_38", with: ["\n"] },
        { text: "§r\n\n" },
        { translate: "float_fc:info.part_39", with: ["\n"] },
        { text: "§r\n\n" },
        { translate: "float_fc:info.part_40", with: ["\n"] },
        { text: "§r\n\n" },
        { translate: "float_fc:info.part_41", with: ["\n"] },
        { text: "§r\n\n" },
        { translate: "float_fc:info.part_42", with: ["\n"] },
        { text: "§r\n\n" },
      ],
    },
    exit: {
      translate: "float_fc:guide_exit",
    },
    soundOnOpen: "item.book.page_turn",
    soundOnClose: "item.book.page_turn",
  })
);
//Floating Fruit Checker
export function leafFallback() {
  var Players,
    TempPlayer,
    nearplayer,
    fruitblock,
    fruitentity = undefined;
  var i,
    x = 0;
  try {
    Players = world.getAllPlayers();
    TempPlayer = undefined;
    for (i = 0; i < Players.length; i++) {
      TempPlayer = Players[i];
      forestryFruitPlusSapPlusTemps.forEach((entityType) => {
        nearplayer = TempPlayer.dimension.getEntities({
          location: TempPlayer.location,
          maxDistance: 30,
          type: entityType,
        });

        for (x = 0; x < nearplayer.length; x++) {
          fruitentity = nearplayer[x];
          fruitblock = fruitentity.dimension.getBlock(fruitentity.location);

          let expectedLeafTypes = [];
          const baseLeafType = entityType.split(":")[1].replace("_leaf", "_leaves");

          if (baseLeafType.startsWith("rainbow_leaves")) {
            expectedLeafTypes = [
              "float_fc:rainbow_leaves_blue",
              "float_fc:rainbow_leaves_cyan",
              "float_fc:rainbow_leaves_green",
              "float_fc:rainbow_leaves_orange",
              "float_fc:rainbow_leaves_pink",
              "float_fc:rainbow_leaves_purple",
              "float_fc:rainbow_leaves_red",
              "float_fc:rainbow_leaves_yellow",
            ];
          } else if (baseLeafType === "pine_cone_leaves") {
            expectedLeafTypes = ["float_fc:pine_leaves"];
          } else if (baseLeafType === "frozen_berry_leaves") {
            expectedLeafTypes = ["float_fc:snow_crystal_leaves"];
          } else if (baseLeafType === "chorus_leaves") {
            expectedLeafTypes = ["float_fc:ender_leaves"];
          } else if (baseLeafType === "cactus_leaves") {
            expectedLeafTypes = ["float_fc:cactus_log"];
          } else {
            expectedLeafTypes = [`float_fc:${baseLeafType}`];
          }

          const isExpectedLeafType = (block) => block && expectedLeafTypes.includes(block.typeId);

          if (
            fruitblock.above().typeId == "minecraft:air" &&
            fruitblock.typeId == "minecraft:air" &&
            fruitblock.north().typeId == "minecraft:air" &&
            fruitblock.south().typeId == "minecraft:air" &&
            fruitblock.east().typeId == "minecraft:air" &&
            fruitblock.west().typeId == "minecraft:air"
          ) {
            fruitentity.runCommand(
              `loot spawn ${fruitblock.location.x} ${fruitblock.location.y} ${
                fruitblock.location.z
              } loot "float/f/${entityType.replace("float_fc:", "")}"`
            );
            fruitentity.triggerEvent(`float_fc:kill_entity`);
          } else if (
            !isExpectedLeafType(fruitblock.above()) &&
            !isExpectedLeafType(fruitblock.below()) &&
            !isExpectedLeafType(fruitblock.north()) &&
            !isExpectedLeafType(fruitblock.south()) &&
            !isExpectedLeafType(fruitblock.east()) &&
            !isExpectedLeafType(fruitblock.west())
          ) {
            fruitentity.runCommand(
              `loot spawn ${fruitblock.location.x} ${fruitblock.location.y} ${
                fruitblock.location.z
              } loot "float/f/${entityType.replace("float_fc:", "")}"`
            );
            fruitentity.triggerEvent(`float_fc:kill_entity`);
          }
        }
      });
    }
  } catch (e) {}
  nearplayer = undefined;
}
system.runInterval(leafFallback, 45);
system.runInterval(spawntrader, 24000);

function spawntrader() {
  let traderplayers = ow.getPlayers({
    tags: ["trader_spawn"],
  });
  traderplayers.forEach((player) => {
    player.runCommand("event entity @e[type=float_fc:sniffer_trader] float_fc:remove");
    player.runCommand("event entity @e[type=float_fc:sapling_trader] float_fc:remove");

    let spawnLocation = player.location;
    let blockAbove;
    let yOffset = 2;

    do {
      blockAbove = player.dimension.getBlock({
        x: Math.floor(spawnLocation.x),
        y: Math.floor(spawnLocation.y) + yOffset,
        z: Math.floor(spawnLocation.z) - 5,
      });
      yOffset++;
    } while (blockAbove.typeId !== "minecraft:air");

    player.runCommand(`summon float_fc:sapling_trader ^ ^${yOffset - 1} ^-5`);
  });
}

var firstTimeQueue = Array();
function processFirstTimers() {
  if (firstTimeQueue.length > 0) {
    showfirsttime(firstTimeQueue.pop());
    system.runTimeout(processFirstTimers, 45);
  }
}
function handleScriptEvents(event) {
  var Players,
    Nearest,
    TempPlayer = undefined;
  var Dist,
    XDist,
    ZDist = 0.0;
  var i = 0;
  try {
    if (event.id == SETTINGS_EVENT_ID) {
      showsettings(event.sourceEntity);
    } else if (event.id == FIRSTTIME_EVENT_ID) {
      if (event.sourceEntity != undefined) {
        firstTimeQueue.push(event.sourceEntity);
      }
      system.runTimeout(processFirstTimers, 45);
    } else if (event.id == "float_fc:turnpage") {
      Players = world.getAllPlayers();
      Nearest = undefined;
      TempPlayer = undefined;
      Dist = Infinity;
      XDist = 0.0;
      ZDist = TempPlayer.location.z - event.sourceEntity.location.z;
      ZDist *= ZDist;
      i = 0;
      for (;;) {
        TempPlayer = Players[i];
        if (String(TempPlayer.name).valueOf() == String(event.message).valueOf()) {
          if (Nearest == undefined) {
            Nearest = TempPlayer;
            XDist *= XDist;
            ZDist = TempPlayer.location.z - event.sourceEntity.location.z;
            ZDist *= ZDist;
            Dist = XDist + ZDist;
          } else {
            XDist = TempPlayer.location.x - event.sourceEntity.location.x;
            XDist *= XDist;
            ZDist = TempPlayer.location.z - event.sourceEntity.location.z;
            ZDist *= ZDist;
            if (Dist > XDist + ZDist) {
              Dist = XDist + ZDist;
              Nearest = TempPlayer;
            }
          }
        }
        i++;
        if (i >= Players.length) {
          if (Nearest == undefined) {
          } else {
            let deltaX = Nearest.location.x - event.sourceEntity.location.x;
            let deltaZ = Nearest.location.z - event.sourceEntity.location.z;
            let targetAngle = Math.atan2(deltaZ, deltaX);
            let playerRotation = Nearest.getRotation().y * (Math.PI / 180);
            let angleDifference = targetAngle - playerRotation;
            angleDifference = ((angleDifference + Math.PI) % (2 * Math.PI)) - Math.PI / 2.0;
            if (angleDifference > 0) {
              system.runTimeout(() => {
                Nearest.dimension.runCommandAsync(`event entity @e[type=float_fc:book,c=1] float_fc:backflip`);
                Nearest.dimension.runCommandAsync(`event entity @e[type=float_fc:book_pedia,c=1] float_fc:backflip`);
              }, 0);
            }
          }
          return;
        }
      }
    } else if (event.id.includes("float_fc:turn_into_sapling") && event.sourceEntity.typeId.includes("_temp")) {
      let sapling,
        result = null;
      sapling = event.sourceEntity.typeId.replace("_temp", "");

      // Check if there's space above the sapling for the tree to grow
      if (!checkTreeGrowSpace(event.sourceEntity.location, event.sourceEntity.dimension)) {
        return;
      }

      //Natural tree growth script event triggers
      if (smallSaplings.has(sapling)) {
        result = growTreeSmall(event.sourceEntity.location, sapling, false, event.sourceEntity.dimension);
      } else if (fruitSaplings.has(sapling)) {
        result = growTreeFruit(event.sourceEntity.location, sapling, false, event.sourceEntity.dimension);
      } else if (mediumSaplings.has(sapling)) {
        result = growTreeMedium(event.sourceEntity.location, sapling, false, event.sourceEntity.dimension);
      } else if (largeSaplings.has(sapling)) {
        result = growTreeLarge(event.sourceEntity.location, sapling, false, event.sourceEntity.dimension);
      } else if (redwooodSaplings.has(sapling)) {
        result = growTreeRedwood(event.sourceEntity.location, sapling, false, event.sourceEntity.dimension);
      } else if (sapling_9_11_13.has(sapling)) {
        result = growTree9_11_13(event.sourceEntity.location, sapling, false, event.sourceEntity.dimension);
      } else if (bonesapling.has(sapling)) {
        result = growTreeBone(event.sourceEntity.location, sapling, false, event.sourceEntity.dimension);
      } else if (mushroomsapling.has(sapling)) {
        result = growTreeMushroom(event.sourceEntity.location, sapling, false, event.sourceEntity.dimension);
      } else if (pinesapling.has(sapling)) {
        result = growTreePine(event.sourceEntity.location, sapling, false, event.sourceEntity.dimension);
      } else if (sapling_15_17_19.has(sapling)) {
        result = growTree15_17_19(event.sourceEntity.location, sapling, false, event.sourceEntity.dimension);
      } else if (vanilla_cherry.has(sapling)) {
        result = growTreeGiantCherry(event.sourceEntity.location, sapling, false, event.sourceEntity.dimension);
      } else if (coconutsapling.has(sapling)) {
        result = growTreeCoconut(event.sourceEntity.location, sapling, false, event.sourceEntity.dimension);
      } else if (avocadoSaplings.has(sapling)) {
        result = growTreeAvocado(event.sourceEntity.location, sapling, false, event.sourceEntity.dimension);
      } else if (pinkOleanderSaplings.has(sapling)) {
        result = growTreePinkOleander(event.sourceEntity.location, sapling, false, event.sourceEntity.dimension);
      } else if (sapling_9_9_11_13.has(sapling)) {
        result = growTree9_9_11_13(event.sourceEntity.location, sapling, false, event.sourceEntity.dimension);
      }
      if (result) {
        pushToCommandQueue(result, event.sourceEntity.location)
          .then(() => {
            system.runTimeout(processCommandQueue, 800);
          })
          .catch((error) => {});
      }
    }
  } catch (e) {}
}
system.afterEvents.scriptEventReceive.subscribe(handleScriptEvents);

function registerForestCraft() {
  // Step 1: Register the base addon (with axes only)
  const baseAddon = {
    name: "Forest Craft",
    item_check: "float_fc:book_spawn_egg",
    axes: [
      {
        id: "float_fc:shear_axe",
        lang: "item.float_fc:shear_axe",
      },
    ],
    on_load: "say Forest Craft X TreeCapitator Compatibility Added!",
  };

  world.getDimension("overworld").runCommand(`scriptevent treecapitator:register_addon ${JSON.stringify(baseAddon)}`);

  // Step 2: Add trees in batches
  registerTreeBatch1();
  registerTreeBatch2();
  registerTreeBatch3();
  registerTreeBatch4();
  registerTreeBatch5();
}

function registerTreeBatch1() {
  const treeBatch1 = {
    addonName: "Forest Craft",
    trees: [
      {
        id: "float_fc:banana_log",
        leaves: {
          types: ["float_fc:banana_leaves"],
          range: 7,
          sides_required: 4,
        },
        shape: {
          log_up_diagonal: false,
          log_up_diagonal_side: false,
          max_branch: 0,
          leaf_diagonal: true,
        },
      },
      {
        id: "float_fc:baobab_log",
        leaves: {
          types: ["float_fc:baobab_leaves"],
          range: 7,
          sides_required: 4,
        },
        shape: {
          log_up_diagonal: true,
          log_up_diagonal_side: true,
          max_branch: 12,
          leaf_diagonal: true,
        },
      },
      {
        id: "float_fc:cherry_log",
        leaves: {
          types: ["float_fc:cherry_leaves"],
          range: 7,
          sides_required: 4,
        },
        shape: {
          log_up_diagonal: true,
          log_up_diagonal_side: true,
          max_branch: 2,
          leaf_diagonal: true,
        },
      },
      {
        id: "float_fc:coconut_log",
        leaves: {
          types: ["float_fc:coconut_leaves"],
          range: 8,
          sides_required: 1,
        },
        shape: {
          log_up_diagonal: true,
          log_up_diagonal_side: false,
          max_branch: 0,
          leaf_diagonal: true,
        },
      },
      {
        id: "float_fc:lemon_log",
        leaves: {
          types: ["float_fc:lemon_leaves"],
          range: 7,
          sides_required: 4,
        },
        shape: {
          log_up_diagonal: true,
          log_up_diagonal_side: true,
          max_branch: 1,
          leaf_diagonal: true,
        },
      },
      {
        id: "float_fc:mango_log",
        leaves: {
          types: ["float_fc:mango_leaves"],
          range: 7,
          sides_required: 4,
        },
        shape: {
          log_up_diagonal: true,
          log_up_diagonal_side: true,
          max_branch: 2,
          leaf_diagonal: true,
        },
      },
      {
        id: "float_fc:maple_log",
        leaves: {
          types: ["float_fc:maple_leaves"],
          range: 7,
          sides_required: 4,
        },
        shape: {
          log_up_diagonal: true,
          log_up_diagonal_side: true,
          max_branch: 2,
          leaf_diagonal: true,
        },
      },
    ],
  };

  world.getDimension("overworld").runCommand(`scriptevent treecapitator:add_trees ${JSON.stringify(treeBatch1)}`);
}

function registerTreeBatch2() {
  const treeBatch2 = {
    addonName: "Forest Craft",
    trees: [
      {
        id: "float_fc:orange_log",
        leaves: {
          types: ["float_fc:orange_leaves"],
          range: 7,
          sides_required: 4,
        },
        shape: {
          log_up_diagonal: true,
          log_up_diagonal_side: true,
          max_branch: 0,
          leaf_diagonal: true,
        },
      },
      {
        id: "float_fc:peach_log",
        leaves: {
          types: ["float_fc:peach_leaves"],
          range: 7,
          sides_required: 4,
        },
        shape: {
          log_up_diagonal: true,
          log_up_diagonal_side: true,
          max_branch: 0,
          leaf_diagonal: true,
        },
      },
      {
        id: "float_fc:pear_log",
        leaves: {
          types: ["float_fc:pear_leaves"],
          range: 6,
          sides_required: 4,
        },
        shape: {
          log_up_diagonal: false,
          log_up_diagonal_side: false,
          max_branch: 0,
          leaf_diagonal: false,
        },
      },
      {
        id: "float_fc:plum_log",
        leaves: {
          types: ["float_fc:plum_leaves"],
          range: 7,
          sides_required: 4,
        },
        shape: {
          log_up_diagonal: true,
          log_up_diagonal_side: true,
          max_branch: 4,
          leaf_diagonal: true,
        },
      },
      {
        id: "float_fc:rainbow_log",
        leaves: {
          types: [
            "float_fc:rainbow_leaves_blue",
            "float_fc:rainbow_leaves_cyan",
            "float_fc:rainbow_leaves_green",
            "float_fc:rainbow_leaves_orange",
            "float_fc:rainbow_leaves_pink",
            "float_fc:rainbow_leaves_purple",
            "float_fc:rainbow_leaves_red",
            "float_fc:rainbow_leaves_yellow",
          ],
          range: 7,
          sides_required: 4,
        },
        shape: {
          log_up_diagonal: true,
          log_up_diagonal_side: true,
          max_branch: 5,
          leaf_diagonal: true,
        },
      },
      {
        id: "float_fc:redwood_log",
        leaves: {
          types: ["float_fc:redwood_leaves"],
          range: 7,
          sides_required: 4,
        },
        shape: {
          log_up_diagonal: true,
          log_up_diagonal_side: true,
          max_branch: 4,
          leaf_diagonal: true,
        },
      },
    ],
  };

  world.getDimension("overworld").runCommand(`scriptevent treecapitator:add_trees ${JSON.stringify(treeBatch2)}`);
}

function registerTreeBatch3() {
  const treeBatch3 = {
    addonName: "Forest Craft",
    trees: [
      {
        id: "float_fc:snow_crystal_log",
        leaves: {
          types: ["float_fc:snow_crystal_leaves"],
          range: 7,
          sides_required: 4,
        },
        shape: {
          log_up_diagonal: false,
          log_up_diagonal_side: false,
          max_branch: 0,
          leaf_diagonal: true,
        },
      },
      {
        id: "float_fc:walnut_log",
        leaves: {
          types: ["float_fc:walnut_leaves"],
          range: 7,
          sides_required: 4,
        },
        shape: {
          log_up_diagonal: true,
          log_up_diagonal_side: true,
          max_branch: 0,
          leaf_diagonal: false,
        },
      },
      {
        id: "float_fc:wisteria_log",
        leaves: {
          types: ["float_fc:wisteria_leaves"],
          range: 10,
          sides_required: 4,
        },
        shape: {
          log_up_diagonal: true,
          log_up_diagonal_side: true,
          max_branch: 6,
          leaf_diagonal: true,
        },
      },
      {
        id: "float_fc:acer_log",
        variants: ["float_fc:acer_wood"],
        leaves: {
          types: ["float_fc:acer_leaves"],
          range: 5,
          sides_required: 4,
        },
        shape: {
          leaf_diagonal: true,
          log_up_diagonal: true,
          log_up_diagonal_side: true,
          max_branch: 3,
        },
      },
      {
        id: "float_fc:ashen_log",
        variants: ["float_fc:ashen_wood"],
        leaves: {
          types: ["float_fc:ashen_leaves"],
          range: 5,
          sides_required: 4,
        },
        shape: {
          leaf_diagonal: true,
          log_up_diagonal: true,
          log_up_diagonal_side: true,
          max_branch: 3,
        },
      },
      {
        id: "float_fc:avocado_log",
        variants: ["float_fc:avocado_wood"],
        leaves: {
          types: ["float_fc:avocado_leaves"],
          range: 5,
          sides_required: 4,
        },
        shape: {
          leaf_diagonal: true,
          log_up_diagonal: true,
          log_up_diagonal_side: true,
          max_branch: 3,
        },
      },
    ],
  };

  world.getDimension("overworld").runCommand(`scriptevent treecapitator:add_trees ${JSON.stringify(treeBatch3)}`);
}

function registerTreeBatch4() {
  const treeBatch4 = {
    addonName: "Forest Craft",
    trees: [
      {
        id: "float_fc:bone_log",
        variants: ["float_fc:bone_wood"],
        leaves: {
          types: ["float_fc:bone_leaves", "float_fc:bone_leaves_flame"],
          range: 5,
          sides_required: 4,
        },
        shape: {
          leaf_diagonal: true,
          log_up_diagonal: true,
          log_up_diagonal_side: true,
          max_branch: 3,
        },
      },
      {
        id: "float_fc:cactus_log",
        variants: ["float_fc:cactus_wood"],
        leaves: {
          types: ["float_fc:cactus_leaves"],
          range: 5,
          sides_required: 4,
        },
        shape: {
          leaf_diagonal: true,
          log_up_diagonal: true,
          log_up_diagonal_side: true,
          max_branch: 3,
        },
      },
      {
        id: "float_fc:ender_log",
        variants: ["float_fc:ender_wood"],
        leaves: {
          types: ["float_fc:ender_leaves"],
          range: 5,
          sides_required: 4,
        },
        shape: {
          leaf_diagonal: true,
          log_up_diagonal: true,
          log_up_diagonal_side: true,
          max_branch: 3,
        },
      },
      {
        id: "float_fc:gold_log",
        variants: ["float_fc:gold_wood"],
        leaves: {
          types: ["float_fc:gold_leaves"],
          range: 5,
          sides_required: 4,
        },
        shape: {
          leaf_diagonal: true,
          log_up_diagonal: true,
          log_up_diagonal_side: true,
          max_branch: 3,
        },
      },
      {
        id: "float_fc:hazelnut_log",
        variants: ["float_fc:hazelnut_wood"],
        leaves: {
          types: ["float_fc:hazelnut_leaves"],
          range: 5,
          sides_required: 4,
        },
        shape: {
          leaf_diagonal: true,
          log_up_diagonal: true,
          log_up_diagonal_side: true,
          max_branch: 3,
        },
      },
      {
        id: "float_fc:juniper_log",
        variants: ["float_fc:juniper_wood"],
        leaves: {
          types: ["float_fc:juniper_leaves"],
          range: 5,
          sides_required: 4,
        },
        shape: {
          leaf_diagonal: true,
          log_up_diagonal: true,
          log_up_diagonal_side: true,
          max_branch: 3,
        },
      },
    ],
  };

  world.getDimension("overworld").runCommand(`scriptevent treecapitator:add_trees ${JSON.stringify(treeBatch4)}`);
}

function registerTreeBatch5() {
  const treeBatch5 = {
    addonName: "Forest Craft",
    trees: [
      {
        id: "float_fc:mushroom_log",
        variants: ["float_fc:mushroom_wood"],
        leaves: {
          types: ["float_fc:mushroom_leaves", "float_fc:mushroom_leaves_inside"],
          range: 5,
          sides_required: 4,
        },
        shape: {
          leaf_diagonal: true,
          log_up_diagonal: true,
          log_up_diagonal_side: true,
          max_branch: 3,
        },
      },
      {
        id: "float_fc:pine_log",
        variants: ["float_fc:pine_wood"],
        leaves: {
          types: ["float_fc:pine_leaves"],
          range: 5,
          sides_required: 4,
        },
        shape: {
          leaf_diagonal: true,
          log_up_diagonal: true,
          log_up_diagonal_side: true,
          max_branch: 3,
        },
      },
      {
        id: "float_fc:scorched_log",
        variants: ["float_fc:scorched_wood"],
        leaves: {
          types: ["float_fc:scorched_leaves", "float_fc:scorched_leaves_flame"],
          range: 5,
          sides_required: 4,
        },
        shape: {
          leaf_diagonal: true,
          log_up_diagonal: true,
          log_up_diagonal_side: true,
          max_branch: 3,
        },
      },
      {
        id: "float_fc:everblue_log",
        variants: ["float_fc:everblue_wood"],
        leaves: {
          types: ["float_fc:everblue_leaves"],
          range: 5,
          sides_required: 4,
        },
        shape: {
          leaf_diagonal: true,
          log_up_diagonal: true,
          log_up_diagonal_side: true,
          max_branch: 3,
        },
      },
      {
        id: "float_fc:pink_oleander_log",
        variants: ["float_fc:pink_oleander_wood"],
        leaves: {
          types: ["float_fc:pink_oleander_leaves"],
          range: 5,
          sides_required: 4,
        },
        shape: {
          leaf_diagonal: true,
          log_up_diagonal: true,
          log_up_diagonal_side: true,
          max_branch: 3,
        },
      },
      {
        id: "float_fc:dawn_redwood_log",
        variants: ["float_fc:dawn_redwood_wood"],
        leaves: {
          types: ["float_fc:dawn_redwood_leaves"],
          range: 5,
          sides_required: 4,
        },
        shape: {
          leaf_diagonal: true,
          log_up_diagonal: true,
          log_up_diagonal_side: true,
          max_branch: 3,
        },
      },
    ],
  };

  world.getDimension("overworld").runCommand(`scriptevent treecapitator:add_trees ${JSON.stringify(treeBatch5)}`);
}

// Register everything when the world initializes
world.afterEvents.worldInitialize.subscribe(() => {
  const treeSpawnTag = `no_tree_spawning`;
  world.setDynamicProperty(treeSpawnTag, true);
  registerForestCraft();
});

north = east = south = west = undefined;

/**
 * Adjusts the height of a fence gate when it's adjacent to vanilla Minecraft walls
 * @param {Block} gateBlock - The fence gate block to check and adjust
 */
function adjustFenceGateHeight(gateBlock) {
  try {
    // Make sure this is a fence gate
    if (!gateTypes.has(gateBlock.typeId)) return;

    // Get the current state of the gate
    const currentStates = gateBlock.permutation.getAllStates();
    const cardinalDirection = currentStates["minecraft:cardinal_direction"];

    // Store the current states that need to be preserved
    const isOpen = currentStates["float_fc:open"] || false;
    const isInWall = currentStates["float_fc:in_wall_bit"] || false;
    const isInvisible = currentStates["float_fc:invisible"] || false;
    const direction = currentStates["float_fc:direction"] || false;

    // Check adjacent blocks based on the fence gate's orientation
    let hasAdjacentWall = false;
    if (cardinalDirection === "north" || cardinalDirection === "south") {
      // For north/south gates, check east and west for walls - both sides must be walls
      const eastBlock = gateBlock.east();
      const westBlock = gateBlock.west();

      hasAdjacentWall = isVanillaWall(eastBlock) || isVanillaWall(westBlock);
    } else {
      // For east/west gates, check north and south for walls - both sides must be walls
      const northBlock = gateBlock.north();
      const southBlock = gateBlock.south();

      hasAdjacentWall = isVanillaWall(northBlock) || isVanillaWall(southBlock);
    }

    // Update the fence gate's permutation to include wall connection state
    // Explicitly set all states to ensure nothing gets lost
    const newPermutation = BlockPermutation.resolve(gateBlock.typeId, {
      "minecraft:cardinal_direction": cardinalDirection,
      "float_fc:open": isOpen,
      "float_fc:in_wall_bit": isInWall,
      "float_fc:invisible": isInvisible,
      "float_fc:direction": direction,
      "float_fc:wall_adjacent": hasAdjacentWall,
    });

    gateBlock.setPermutation(newPermutation);
  } catch (err) {
    // Silent fail to prevent errors from breaking other functionality
  }
}

/**
 * Checks if a block is a vanilla Minecraft wall
 * @param {Block} block - The block to check
 * @returns {boolean} True if the block is a vanilla wall, false otherwise
 */
function isVanillaWall(block) {
  if (!block) return false;

  // Check for all vanilla wall types
  return block.typeId.startsWith("minecraft:") && block.typeId.endsWith("_wall");
}
