console.warn('main.js loaded');
import { world, system, Player, ScoreboardIdentity } from "@minecraft/server"
import { ActionFormData, MessageFormData, ModalFormData } from "@minecraft/server-ui"
import { weatherTimeSettings } from "./wat.js";
import { moneyTransfer } from "./moneyUtils.js";
import { personalSettings } from "./effect.js";
import { showBlockMenu } from "../break.js";
import { cachedPlayers } from '../lag/pvp.js';
import { getOwner } from '../custom/custom6.js';
import { openPlotManagement } from '../custom/custom6.js';



system.runInterval(() => {
  for (const player of cachedPlayers) {
    const tagsArr = player.getTags();
    if (tagsArr.length === 0) continue;

    // Use Set for O(1) lookups
    const tags = new Set(tagsArr);

    // === CHECKPOINT SAVE ===
    if (tags.delete("hasCheckpoint")) {
      const loc = player.location;
      player.setDynamicProperty("checkpoint_x", loc.x);
      player.setDynamicProperty("checkpoint_y", loc.y);
      player.setDynamicProperty("checkpoint_z", loc.z);
      player.setDynamicProperty("checkpoint_dim", player.dimension.id);

      player.runCommandAsync(`title @s actionbar §l§a+ §r§aCheckpoint §l+`);
      player.playSound("random.orb");
      player.removeTag("hasCheckpoint"); // safe double remove
    }

    // === CHECKPOINT CLEAR ===
    if (tags.delete("hasNoCheckpoint")) {
      player.setDynamicProperty("checkpoint_x", undefined);
      player.setDynamicProperty("checkpoint_y", undefined);
      player.setDynamicProperty("checkpoint_z", undefined);
      player.setDynamicProperty("checkpoint_dim", undefined);

      player.sendMessage("§cCheckpoint cleared!");
      player.playSound("random.break");
      player.removeTag("hasNoCheckpoint");
    }

    // === TELEPORTS ===
    if (tags.delete("Lobby")) {
      player.removeTag("Lobby");
      player.teleport({ x: 0, y: 200, z: 0 }, { facingLocation: { x: 0, y: 200, z: 1 } });
      system.runTimeout(() => {
        player.runCommandAsync(`particle minecraft:knockback_roar_particle ~ ~ ~`);
        player.playSound("item.trident.return");
        player.addEffect("blindness", 20, { amplifier: 0, showParticles: false });
      }, 1);
    }

    if (tags.delete("VIPZone")) {
      player.removeTag("VIPZone");
      player.teleport({ x: 4000, y: 5, z: 4000 }, { facingLocation: { x: 4001, y: 5, z: 4000 } });
      system.runTimeout(() => {
        player.runCommandAsync(`particle minecraft:knockback_roar_particle ~ ~ ~`);
        player.playSound("mob.endermen.portal");
        player.addEffect("blindness", 20, { amplifier: 0, showParticles: false });
      }, 1);
    }

    if (tags.delete("VIPIsland")) {
      player.removeTag("VIPIsland");
      player.teleport({ x: -4000, y: 6, z: -4000 }, { facingLocation: { x: -4000, y: 6, z: -3999 } });
      system.runTimeout(() => {
        player.runCommandAsync(`particle minecraft:knockback_roar_particle ~ ~ ~`);
        player.playSound("mob.endermen.portal");
        player.addEffect("blindness", 20, { amplifier: 0, showParticles: false });
      }, 1);
    }

    // === TELEPORT TO CHECKPOINT ===
    if (tags.delete("Tpcheckpoint")) {
      player.removeTag("Tpcheckpoint");

      const x = player.getDynamicProperty("checkpoint_x");
      const y = player.getDynamicProperty("checkpoint_y");
      const z = player.getDynamicProperty("checkpoint_z");
      const dimId = player.getDynamicProperty("checkpoint_dim");

      if (x != null && y != null && z != null && dimId) {
        const dim = world.getDimension(dimId);
        if (dim) {
          player.teleport({ x, y, z }, { dimension: dim });
          player.sendMessage("§aTeleported to your checkpoint!");
          player.playSound("mob.endermen.portal");
          system.runTimeout(() => {
            player.runCommandAsync(`particle minecraft:knockback_roar_particle ~ ~ ~`);
            player.addEffect("blindness", 20, { amplifier: 0, showParticles: false });
          }, 1);
        } else {
          player.sendMessage("§cCheckpoint dimension not found.");
          player.playSound("note.bass");
        }
      } else {
        player.sendMessage("§cNo checkpoint found.");
        player.playSound("note.bass");
      }
    }
  }
}, 1); // run every 2 ticks instead of every tick




// === PRESSURE PLATE BOOST SYSTEM ===
world.afterEvents.pressurePlatePush.subscribe(ev => {
    const player = ev.source;

    // Make sure it's a player
    if (!player || player.typeId !== "minecraft:player") return;

    // Check the pressure plate type
    const block = ev.block;
    const plateId = block.typeId;

    if (plateId === "minecraft:stone_pressure_plate" || plateId === "minecraft:dark_oak_pressure_plate") {
        // Get the player's look direction
        const dir = player.getViewDirection();

        // Apply knockback boost
        player.applyKnockback(dir.x, dir.z, 6, 1);

        // Play sound effect
        player.playSound("mob.enderdragon.flap");
    }
});


function getScore(player, objectiveName) {
    try {
        const objective = world.scoreboard.getObjective(objectiveName);
        if (!objective) return 0;
        return objective.getScore(player) ?? 0; // pass the player object directly
    } catch {
        return 0;
    }
}

// === Helpers ===
function formatMoney(value) {
  if (value >= 1_000_000_000) return (value / 1_000_000_000).toFixed(2) + "B";
  if (value >= 1_000_000) return (value / 1_000_000).toFixed(2) + "M";
  if (value >= 1_000) return (value / 1_000).toFixed(2) + "k";
  return value.toString();
}

const rankTagMap = {
  "gwim:VIP": "",
  "gwim:VIPPlus": "",
  "gwim:Elite": "",
  "gwim:ElitePlus": "",
  "gwim:God": "",
  "gwim:Miner": "§l§aMiner",
  "gwim:Healer": "§l§dHealer",
  "gwim:Warrior": "§l§cWarrior",
  "gwim:Owner": "",
  "gwim:Admin": ""
};

// === Zone Config ===
const skywarsCenter = { x: 5000, y: 60, z: 5000 };
const skywarsRadiusSq = 100 * 100;

function isInsideZone(pos, center, radiusSq) {
  const dx = pos.x - center.x;
  const dy = pos.y - center.y;
  const dz = pos.z - center.z;
  return (dx * dx + dy * dy + dz * dz) <= radiusSq;
}

// === Prebuilt Scoreboard Parts ===
const scoreboardHeader = [
  { text: "§r§l§8<§b Server Info §8>§r" },
  { text: "\n◆ §bServer: §aMINING SIM§r" },
  { text: "\n◆ §bCreator: §rFly Sakib§r" },
  { text: "\n\n§r§l§8<§d Your Stats §8>§r" },
  { text: "\n◆ §bTime Played:§r " },
  { score: { name: "@s", objective: "h" } },
  { text: "h" }
];

const scoreboardFooter = [
  { text: "\n\n§r§l§8<§a Server Activity §8>§r" },
  { text: "\n§r◆ §eClearlag: " },
  { score: { name: "ClearlagTimer", objective: "clearlag" } },
  { text: "s" },
  { text: "\n§r◆ §aOnline: " },
  { score: { name: "@s", objective: "Online" } },
  { text: "\n§r◆ §cMobs Remaining: " },
  { score: { name: "@s", objective: "Mob" } }
];

// === Cache scoreboard objects ===
const moneyObj = world.scoreboard.getObjective("Money");

// === Main loop ===
system.runInterval(() => {
  for (const player of cachedPlayers) {
    const tags = player.getTags();

    // --- Quick void protection
    if (player.location.y < -60) {
      player.teleport({ x: 0, y: 200, z: 0 });
    }

    // --- Money
    const money = moneyObj?.getScore(player) ?? 0;
    const moneyFormatted = formatMoney(money);

    // --- Zone restrictions
    if (isInsideZone(player.location, skywarsCenter, skywarsRadiusSq)) {
      if (player.getDynamicProperty("God_mine3x3_toggle") === true ||
          player.getDynamicProperty("ElitePlus_mine3x3_toggle") === true) {
        player.setDynamicProperty("God_mine3x3_toggle", false);
        player.setDynamicProperty("ElitePlus_mine3x3_toggle", false);
        player.sendMessage("§cYour 3×3 mining ability disabled in SkyWars!");
        player.playSound("random.break");
      }
    }

    // --- Starter Kit (only runs once per player)
    if (!tags.includes("Welcome")) {
      player.sendMessage("§l§a> Welcome to the server!\n> Please read the rules before playing!");
      player.playSound("random.orb");
      player.teleport({ x: 0, y: 200, z: 0 });
      // batch give instead of multiple commands
      player.runCommandAsync(`replaceitem entity @s slot.armor.head 1 leather_helmet`);
  player.runCommandAsync(`replaceitem entity @s slot.armor.chest 1 leather_chestplate`);
  player.runCommandAsync(`replaceitem entity @s slot.armor.legs 1 leather_leggings`);
  player.runCommandAsync(`replaceitem entity @s slot.armor.feet 1 leather_boots`);
      player.runCommandAsync(`give @s wooden_sword`);
      player.runCommandAsync(`give @s wooden_pickaxe`);
      player.runCommandAsync(`give @s wooden_axe`);
      player.runCommandAsync(`give @s wooden_shovel`);
      player.runCommandAsync(`give @s dried_kelp 32`);
      player.runCommandAsync(`tag @s add Welcome`);
    }

    // --- Locked Slot (only runs once)
    if (!tags.includes("lock")) {
      const container = player.getComponent("inventory")?.container;
      const slotItem = container?.getItem(8);
      if (!slotItem || slotItem.typeId !== "pa:lobby") {
        player.runCommandAsync(
          `replaceitem entity @s slot.hotbar 8 pa:lobby 1 5 {"item_lock":{"mode":"lock_in_inventory"}}`
        );
        player.runCommandAsync(`tag @s add lock`);
      }
    }

    // --- Scoreboard
    if (tags.includes("hide_scoreboard")) {
      player.runCommandAsync(`titleraw @s title {"rawtext":[{"text":" "}]}`);
      continue;
    }

    let matchedRank = "";
    for (const [tag, display] of Object.entries(rankTagMap)) {
      if (tags.includes(tag)) {
        matchedRank = display;
        break;
      }
    }

    // Build once then show
    const scoreboardRawtext = [
      ...scoreboardHeader,
      { text: `\n◆ §bBalance: §a$${moneyFormatted}` },
      { text: `\n§r◆ §bRank: ${matchedRank}` },
      { text: "\n§r◆ §bKills:§r " },
      { score: { name: "@s", objective: "player_kills" } },
      { text: "\n§r◆ §bDeaths:§r " },
      { score: { name: "@s", objective: "player_deaths" } },
      ...scoreboardFooter
    ];

    player.runCommandAsync(
      `titleraw @s title ${JSON.stringify({ rawtext: scoreboardRawtext })}`
    );
  }
}, 7); // doubled interval to cut load in half

// === Clearlag ===
function handleClearlagCountdown() {
  const objective = world.scoreboard.getObjective("clearlag");
  if (!objective) return;

  const fakeName = "ClearlagTimer";
  const score = objective.getScore(fakeName);

  if (score == null) {
    objective.setScore(fakeName, 1200);
    return;
  }

  if (score === 30) world.sendMessage("§b§l>> §r§bClear Lag in 30 seconds...");
  if (score === 0) {
    world.sendMessage("§b§l>> §r§bClear Lag has been performed");
    const dim = world.getDimension("overworld");
    dim.runCommandAsync(`tp @e[type=item] 1000 7 1005`);
    dim.runCommandAsync(`kill @e[type=xp_orb]`);
    dim.runCommandAsync(`kill @e[type=arrow]`);
    objective.setScore(fakeName, 1200);
    return;
  }
  objective.setScore(fakeName, score - 1);
}

system.runInterval(handleClearlagCountdown, 20);

function teleportToLobby(player) {
    const over = world.getDimension("minecraft:overworld");
    over.runCommandAsync(`tp "${player.name}" 0 200 0 facing 0 200 1`).then(() => {
        system.runTimeout(() => {
            player.runCommandAsync(`particle minecraft:knockback_roar_particle ~ ~ ~`);
            player.runCommandAsync(`clearspawnpoint @s`);
            player.addEffect("blindness", 20, {
                amplifier: 0,
                showParticles: false
            });
            player.playSound("item.trident.return");
        }, 1);
    });
}

function main(player) {
    new ActionFormData()
        .title(`§l§bServer Menu`)
        .body(`Choose an option Below!`)
        .button(`§lPlayer Info's\n§r§7[ Click to View ]`, "textures/items/compass_item")
        .button(`§l§2Shop §r& §l§gSell\n§r§7[ Click to View ]`, "textures/ui/icon_recipe_equipment")
        .button('§aMoney Transfer\n§r§7[ Click to View ]', "textures/ui/money")
        .button('§aCheckpoint Settings\n§r§7[ Click to View ]', "textures/ui/online")
        .button('§l§6Lobby\n§r§7[ Click to Teleport ]', "textures/ui/world_glyph_color_2x") // ← moved here
        .button('Settings\n§r§7[ Click to View ]', "textures/ui/dev_glyph_color")
        .button('About\n§r§7[ Click to View ]', "textures/ui/infobulb")
        .show(player).then(r => {
            switch (r.selection) {
                case 0: return openPlayerLocationGUI(player);
                case 1: return quickmenu(player);
                case 2: return moneyTransfer(player);
                case 3: return checkpoint(player);
                case 4: return teleportToLobby(player); // ← NEW
                case 5: return settings(player);
                case 6: return about(player);
            }
        });
}
    

function checkpoint(player) {
    new ActionFormData()
        .title(`§lCheckpoint Settings`)
        .body(`Choose an option Below!`)
        .button('§aPrevious Checkpoint\n§7[ Click to Teleport ]', "textures/ui/refresh_light")
        .button('§cClear Checkpoint\n§7[ Click to Remove ]', "textures/ui/redX1")
        .button('§l§cBack', "textures/ui/arrow_left")
        .show(player)
        .then(r => {
            switch (r.selection) {
                case 0: { // Add tag to trigger teleport
                    player.addTag("Tpcheckpoint");
                    break;
                }
                case 1: { // Add tag to trigger clear
                    player.addTag("hasNoCheckpoint");
                    break;
                }
                case 2: { // Back
                    main(player);  // Replace with your main menu function
                    break;
                }
            }
        });
}

function quickmenu(player) {
    const isVIP = player.hasTag("VIPPurchased");

    const form = new ActionFormData()
        .title('§lShop & Sell')
        .body('Choose an option below!')
        .button('§2§lShop\n§r§7[ Click to View ]', "textures/ui/icon_recipe_equipment")
        .button('§e§lMinerals Sell\n§r§7[ Click to View ]', "textures/ui/trade_icon") // fixed color
        .button('§p§lWoods Sell\n§r§7[ Click to View ]', "textures/ui/trade_icon");  // fixed color

    if (isVIP) {
        form.button('§e§lVIP Minerals Sell\n§r§7[ Click to View ]', "textures/ui/trade_icon");
    }

    form.button('§l§cBack', "textures/ui/arrow_left");

    form.show(player).then(r => {
        if (r.canceled) return;

        if (!isVIP) {
            switch (r.selection) {
                case 0: return shopui(player);
                case 1: return showSellMenu(player);
                case 2: return showWoodSellMenu(player);
                case 3: return main(player);
            }
        } else {
            switch (r.selection) {
                case 0: return shopui(player);
                case 1: return showSellMenu(player);
                case 2: return showWoodSellMenu(player);
                case 3: return showBlockMenu(player); // VIP-only
                case 4: return main(player);
            }
        }
    });
}

function settings(player) {
    const form = new ActionFormData()
        .title("§lSettings")
        .body("Choose a Settings Below!")
        .button('Weather & Time\n§r§7[ Click to Configure ]', "textures/ui/weather") // 0
        .button('§cGamerules\n§r§7[ Click to Configure ]', "textures/ui/dev_glyph_color") // 1
        .button(
            player.hasTag("hide_scoreboard")
                ? '§aShow §rScoreboard\n§r§7[ Click to Show ]'
                : '§cHide §rScoreboard\n§r§7[ Click to Hide ]',
            "textures/ui/perspective" // 2
        )
        .button(
  '§eRank Settings\n§r§7[ Click to Configure ]',
  "textures/ui/debug_glyph_color"
)
        .button('§cClear My Data\n§r§c[ Not Recommended ]', "textures/ui/icon_trash") // 4
        .button('§l§cBack', "textures/ui/arrow_left"); // 5

    form.show(player).then(res => {
        if (res.canceled) return;
        switch (res.selection) {
            case 0: weatherTimeSettings(player); break;
            case 1: openToggleMenu(player); break;
            case 2: toggleScoreboard(player); break;
            case 3: personalSettings(player); break;
            case 4: cleardata(player); break;
            case 5: main(player); break;
        }
    });
}
    


    
    


function toggleScoreboard(player) {
    if (player.hasTag("hide_scoreboard")) {
        player.removeTag("hide_scoreboard");
        player.playSound("random.orb");
        player.sendMessage("§aScoreboard is now visible!");
    } else {
        player.addTag("hide_scoreboard");
        player.playSound("random.orb");
        player.sendMessage("§cScoreboard is now hidden!");
    }
}

function cleardata(player) {
	new MessageFormData()
        .title("§lWarning")
        .body('Are you sure?\n\nThis will Clear all of your data including\nYour §bMoney, Rank, Kills, Deaths, Time played§r\nYour §binventory§r will also be cleared\nExcept Your §dEnder chest §r\n\n§eThink Twice Before Confirming!\n§rAdmins §rCannot help you if you confirm this action by mistake')
        .button1("Cancel")
        .button2("Confirm")
        .show(player)
        .then(response => {
            if (response.selection === 1) {
                player.runCommandAsync("tag @s remove lock")
                player.runCommandAsync("tag @s remove Welcome")
                player.runCommandAsync("clear @s")
                player.runCommandAsync("tag @s remove gwim:Miner")
                player.runCommandAsync("tag @s remove gwim:Healer")
                player.runCommandAsync("tag @s remove gwim:Warrior")
                player.runCommandAsync("tag @s remove VIPPurchased")
                player.runCommandAsync("tag @s remove gwim:Owner")
                player.runCommandAsync("tag @s remove gwim:Admin")
                player.runCommandAsync("scoreboard players set @s Money 0")
                player.runCommandAsync("scoreboard players set @s player_kills 0")
                player.runCommandAsync("scoreboard players set @s player_deaths 0")
                player.runCommandAsync("scoreboard players set @s h 0")
                player.runCommandAsync("scoreboard players set @s min 0")
                player.runCommandAsync("scoreboard players set @s sec 0")
            }
            if (response.selection === 0) settings(player)
        })
}

// Create a global object to store our custom gamerules
const customGamerules = {
    doDaylightCycle: true,
    doWeatherCycle: true,
    doMobLoot: true,
    fallDamage: true,
    fireDamage: true,
    drowningDamage: true,   // Added drowning damage
    locatorBar: true,       // Added locator bar
    arrowOrbSound: true     // NEW: Orb Sound on arrow hit
};

// Replace the customGamerules object with these functions:
function getGamerule(rule) {
    return world.getDynamicProperty(rule) ?? true; // Defaults to true if not set
}

function setGamerule(rule, value) {
    world.setDynamicProperty(rule, value);

    // Apply built-in gamerule if applicable
    const overworld = world.getDimension("overworld");
    if (["doDaylightCycle", "doWeatherCycle", "doMobLoot", "fallDamage", "fireDamage", "drowningDamage", "locatorbar"].includes(rule)) {
        overworld.runCommandAsync(`gamerule ${rule} ${value}`);
    }
}

function openToggleMenu(player) {
    let form = new ModalFormData()
        .title("§lGamerules")
        .toggle("Do Daylight Cycle", getGamerule("doDaylightCycle"))
        .toggle("Do Weather Cycle", getGamerule("doWeatherCycle"))
        .toggle("Mob Loot", getGamerule("doMobLoot"))
        .toggle("Fall Damage", getGamerule("fallDamage"))
        .toggle("Fire Damage", getGamerule("fireDamage"))
        .toggle("Drowning Damage", getGamerule("drowningDamage"))
        .toggle("Locator Bar", getGamerule("locatorbar"))
        .toggle("Lightning on Player Death", getGamerule("lightningOnKill"))
        .toggle("Ding Sound on Arrow Hit", getGamerule("arrowOrbSound")); // NEW

    form.show(player).then(response => {
        if (response.canceled) return;

        setGamerule("doDaylightCycle", response.formValues[0]);
        setGamerule("doWeatherCycle", response.formValues[1]);
        setGamerule("doMobLoot", response.formValues[2]);
        setGamerule("fallDamage", response.formValues[3]);
        setGamerule("fireDamage", response.formValues[4]);
        setGamerule("drowningDamage", response.formValues[5]);
        setGamerule("locatorbar", response.formValues[6]);
        setGamerule("lightningOnKill", response.formValues[7]);
        setGamerule("arrowOrbSound", response.formValues[8]); // NEW

        player.sendMessage("§eGamerules saved");
        player.playSound("random.pop");
        player.runCommandAsync("title @a actionbar §eGamerules saved");
    });
}

// Orb sound on arrow hit (controlled by gamerule)
const hostileMobs = [
    "minecraft:zombie",
    "minecraft:skeleton",
    "minecraft:creeper",
    "minecraft:spider",
    "minecraft:wither",
    "minecraft:blaze",
    "minecraft:pillager",
    "minecraft:evocation_illager",
    "minecraft:vindicator",
    "minecraft:ravager",
    "minecraft:stray",
    "minecraft:drowned",
    "minecraft:warden",
    "minecraft:ender_dragon",
    "minecraft:bogged",
    "minecraft:husk",
    "minecraft:wither_skeleton",
    "minecraft:witch",
    "minecraft:breeze",
    "minecraft:player",
    "minecraft:cave_spider",
];

world.afterEvents.entityHurt.subscribe(event => {
    try {
        if (!getGamerule("arrowOrbSound")) return;

        const { hurtEntity, damageSource } = event;
        if (!damageSource) return;

        const proj = damageSource.damagingProjectile;
        const shooter = damageSource.damagingEntity;

        if (!proj || proj.typeId !== "minecraft:arrow") return;
        if (!shooter || shooter.typeId !== "minecraft:player") return;
        if (!hostileMobs.includes(hurtEntity.typeId)) return;

        shooter.runCommandAsync(`playsound random.orb @s ~~~ 0.5 0.5 0.5`);
    } catch (err) {
        console.warn(`entityHurt handler error: ${err}`);
    }
});

world.afterEvents.entityDie.subscribe(event => {
    const dead = event.deadEntity;
    if (!dead || dead.typeId !== "minecraft:player") return;

    // Check if Lightning on Kill is enabled
    if (!getGamerule("lightningOnKill")) return;

    const loc = dead.location;
    dead.dimension.spawnEntity("minecraft:lightning_bolt", loc);
    world.getPlayers().forEach(p => p.runCommandAsync(`playsound ambient.weather.thunder @s`));
});


const locations = [
    { name: "§6§lLobby", x: 0, y: 200, z: 0, r: 200 },
    { name: "§l§bP§eV§bP", x: -1000, y: 32, z: 1000, r: 200 },
    { name: "§l§bP§eV§cE", x: 1035, y: 0, z: -1014, r: 200 },
    { name: "§5§lParkour", x: -2000, y: 100, z: -1870, r: 200 },
    { name: "§c§lBow§bWars", x: -3000, y: 5, z: 3000, r: 200 },
    { name: "§l§dBlock§6Drop", x: 2000, y: 5, z: -2000, r: 300 },
    { name: "§l§bSky§eWars", x: 5000, y: 44, z: 5000, r: 100 },
    { name: "§8§lGarbage Bank", x: 1000, y: 5, z: 1000, r: 100 },
    { name: "§l§bAdmin Shop", x: 3000, y: 5, z: 3000, r: 200 },
    { name: "§l§3School §e& §bNeighbourhood", x: -1918, y: 40, z: 1779, r: 300 },
    { name: "§l§eRelaxing Park", x: -3012, y: 5, z: -3029, r: 400 },
    { name: "§l§dShulker Box Place", x: -5000, y: 4, z: -5000, r: 40 },
    { name: "§l§tThe Land", x: 10000, y: 5, z: 10000, r: 300 },
    { name: "§l§eVIP §gZone", x: 4000, y: 5, z: 4000, r: 200 },
    { name: "§l§eVIP Island", x: -4000, y: 5, z: -4000, r: 600 },
    { name: "§l§aMINING SIMULATOR", x: 3994, y: 20, z: -4000, r: 300 },
    { name: "§l§aMINING AREA 2", x: 3000, y: 4, z: -3000, r: 200 },
    { name: "§l§bTHE END", dimension: "minecraft:the_end" }
];

function getPlayerLocationName(player) {
    if (player.dimension.id === "minecraft:the_end") return "§l§bTHE END";
    let pos = player.getHeadLocation();
    for (let loc of locations) {
        if (loc.dimension) continue;
        let dx = Math.abs(pos.x - loc.x);
        let dz = Math.abs(pos.z - loc.z);
        if (dx <= loc.r && dz <= loc.r) return loc.name;
    }
    return "§7Unknown Location";
}

// Improved getRankTag with multiple tags and priority
function getRankTag(player) {
    const rankPriority = [
        { tag: "gwim:VIP", display: "" },
        { tag: "gwim:Warrior", display: "§l§cWarrior" },
        { tag: "gwim:Miner", display: "§l§aMiner" },
        { tag: "gwim:Healer", display: "§l§dHealer" },
        { tag: "gwim:Owner", display: "" },
        { tag: "gwim:Admin", display: "" },
        { tag: "gwim:VIPPlus", display: "" },
        { tag: "gwim:Elite", display: "" },
        { tag: "gwim:ElitePlus", display: "" },
        { tag: "gwim:God", display: "" },
        
    ];

    // Check ranks in priority order
    for (const rank of rankPriority) {
        if (player.hasTag(rank.tag)) {
            return rank.display;
        }
    }

    // If player has some other gwim tag, show it in gray
    for (const tag of player.getTags()) {
        if (tag.startsWith("gwim:")) {
            const rankName = tag.substring("gwim:".length);
            return `§7${rankName}`;
        }
    }

    return ""; // Default if no rank found
}

function showPlayerStatsForm(viewer, target) {
    const h = getScore(target, "h");
    const min = getScore(target, "min");
    const sec = getScore(target, "sec");
    const money = getScore(target, "Money");
    const kills = getScore(target, "player_kills");
    const deaths = getScore(target, "player_deaths");
    const rank = getRankTag(target);

    const message = `  §lStats of §r${target.name}\n\n` +
        `§r -§bTime Played > §f${h}h ${min}min ${sec}sec\n` +
        `§r -§bBalance > §f$${money}\n` +
        `§r -§bRank > ${rank}\n` +
        `§r -§bKills > §f${kills}\n` +
        `§r -§bDeaths > §f${deaths}\n\n`;

    new MessageFormData()
        .title("§lStats")
        .body(message)
        .button1("Back")
        .button2("Okay")
        .show(viewer)
        .then(response => {
            if (response.selection === 0) {
                openPlayerLocationGUI(viewer);
            }
        });
}

function openPlayerLocationGUI(player) {
    let form = new ActionFormData()
        .title("§lPlayer Info's")
        .body("Click a player to view their stats!");

    let players = Array.from(world.getPlayers());

    for (let p of players) {
        let locationName = getPlayerLocationName(p);
        form.button(`§r${p.name}\n§r${locationName}`, "textures/ui/icon_steve");
    }

    form.button("§l§cBack", "textures/ui/arrow_left");

    form.show(player).then(response => {
        if (response.canceled) return;
        let index = response.selection;
        if (index === players.length) {
            main(player); // back to main menu
        } else {
            let selectedPlayer = players[index];
            if (selectedPlayer) {
                showPlayerStatsForm(player, selectedPlayer);
            }
        }
    });
}

function removeWood(player, typeId, amount) {
    const inventory = player.getComponent("minecraft:inventory").container;
    for (let slot = 0; slot < inventory.size; slot++) {
        const item = inventory.getItem(slot);
        if (!item || item.typeId !== typeId) continue;

        if (item.amount <= amount) {
            amount -= item.amount;
            inventory.setItem(slot, undefined);
        } else {
            const reducedItem = item.clone();
            reducedItem.amount = item.amount - amount;
            inventory.setItem(slot, reducedItem);
            amount = 0;
        }

        if (amount <= 0) break;
    }
}

function showWoodSellMenu(player) {
    const inventory = player.getComponent("minecraft:inventory").container;
    const moneyObjective = world.scoreboard.getObjective("Money");

    const woodItems = [
    { type: "minecraft:oak_log", name: "Oak Log", displayName: "§6§lOak Log", price: 30 },       // Brownish
    { type: "minecraft:birch_log", name: "Birch Log", displayName: "§e§lBirch Log", price: 35 }, // Yellow
    { type: "minecraft:spruce_log", name: "Spruce Log", displayName: "§2§lSpruce Log", price: 38 }, // Dark Green
    { type: "minecraft:acacia_log", name: "Acacia Log", displayName: "§c§lAcacia Log", price: 40 }, // Red
    { type: "minecraft:dark_oak_log", name: "Dark Oak Log", displayName: "§8§lDark Oak Log", price: 42 }, // Dark Gray
    { type: "minecraft:jungle_log", name: "Jungle Log", displayName: "§a§lJungle Log", price: 45 }, // Light Green
    { type: "minecraft:cherry_log", name: "Cherry Log", displayName: "§d§lCherry Log", price: 48 }, // Pink
    { type: "minecraft:pale_oak_log", name: "Pale Oak Log", displayName: "§f§lPale Oak Log", price: 50 } // White
];

    const inventoryCounts = {};
    let totalSellable = 0;
    for (let slot = 0; slot < inventory.size; slot++) {
        const item = inventory.getItem(slot);
        if (!item) continue;
        inventoryCounts[item.typeId] = (inventoryCounts[item.typeId] || 0) + item.amount;
    }
    for (const wood of woodItems) {
        totalSellable += inventoryCounts[wood.type] ?? 0;
    }

    if (totalSellable === 0) {
        player.sendMessage("§cYou don't have any logs to sell.");
        player.playSound("note.bass");
        return;
    }

    const form = new ModalFormData()
        .title("§lWoods Sell")
        .dropdown("§7Select a mode", [
            "§aManual Sell (Use sliders)",
            `§cSell All (${totalSellable})`
        ]);

    const priceInfo = woodItems.map(i => `§7- ${i.displayName} §f= §a$${i.price}`).join("\n");
    const currentMoney = moneyObjective?.getScore(player) ?? 0;

    form.slider(
        `§l§6Welcome to Woods Sell!\n§r§fYou have §a$${currentMoney}§f.\nUse the sliders below to sell specific amounts,\nor choose §c"Sell All"§f above to sell everything.\n\n§l§eSellable Logs:\n${priceInfo}`,
        0, 0, 0, 0
    );

    for (const wood of woodItems) {
        const count = inventoryCounts[wood.type] ?? 0;
        form.slider(`${wood.displayName} §7(0–${count})`, 0, count, 1, 0);
    }

    form.show(player).then(res => {
        if (res.canceled) return;

        const selectedMode = res.formValues[0];
        const sliderValues = res.formValues.slice(2);

        if (selectedMode === 1) {
            // SELL ALL MODE
            let totalAmount = 0;
            let totalMoney = 0;
            let summaryLines = [];

            for (const wood of woodItems) {
                const count = inventoryCounts[wood.type] ?? 0;
                if (count > 0) {
                    const earn = count * wood.price;
                    totalAmount += count;
                    totalMoney += earn;
                    summaryLines.push(`${wood.displayName} §rx §e${count} §7= §a$${earn}§r`);
                }
            }

            const confirm = new MessageFormData()
                .title("§lConfirm Sell All")
                .body(`You're selling:\n\n${summaryLines.join("\n")}\n\n§l§fTotal: §a§l$${totalMoney}§r`)
                .button1("§cCancel")
                .button2("§aConfirm");

            confirm.show(player).then(confirmRes => {
                if (confirmRes.selection !== 1) {
                    player.sendMessage("§cSell cancelled.");
                    player.playSound("note.bass");
                    return;
                }

                for (const wood of woodItems) {
                    const count = inventoryCounts[wood.type] ?? 0;
                    if (count > 0) removeWood(player, wood.type, count);
                }

                if (moneyObjective) {
                    const current = moneyObjective.getScore(player) ?? 0;
                    moneyObjective.setScore(player, current + totalMoney);
                }

                player.sendMessage(`§gYou sold ${totalAmount} logs for §a$${totalMoney}`);
                player.playSound("random.orb");
            });

        } else {
            // MANUAL SLIDER MODE
            let totalAmount = 0;
            let totalMoney = 0;
            let summaryLines = [];

            for (let i = 0; i < sliderValues.length; i++) {
                const amount = sliderValues[i];
                const wood = woodItems[i];
                if (amount > 0) {
                    const earn = amount * wood.price;
                    totalAmount += amount;
                    totalMoney += earn;
                    summaryLines.push(`${wood.displayName} §rx §e${amount} §7= §a$${earn}§r`);
                }
            }

            if (totalAmount === 0) {
                player.sendMessage("§cNothing selected to sell!");
                player.playSound("note.bass");
                quickmenu(player) 
                return;
            }

            const confirm = new MessageFormData()
                .title("§lConfirm Sale")
                .body(`You're selling:\n\n${summaryLines.join("\n")}\n\n§l§fTotal: §a§l$${totalMoney}§r`)
                .button1("§cCancel")
                .button2("§aConfirm");

            confirm.show(player).then(confirmRes => {
                if (confirmRes.selection !== 1) {
                    player.sendMessage("§cSell cancelled.");
                    player.playSound("note.bass");
                    quickmenu(player) 
                    return;
                }

                for (let i = 0; i < sliderValues.length; i++) {
                    const amountToRemove = sliderValues[i];
                    if (amountToRemove > 0) {
                        removeWood(player, woodItems[i].type, amountToRemove);
                    }
                }

                if (moneyObjective) {
                    const current = moneyObjective.getScore(player) ?? 0;
                    moneyObjective.setScore(player, current + totalMoney);
                }

                player.sendMessage(`§gYou sold ${totalAmount} logs for §a$${totalMoney}`);
                player.playSound("random.orb");
                quickmenu(player) 
            });
        }
    });
}


function removeItems(player, typeId, amount) {
    const inventory = player.getComponent("minecraft:inventory").container;
    for (let slot = 0; slot < inventory.size; slot++) {
        const item = inventory.getItem(slot);
        if (!item || item.typeId !== typeId) continue;

        if (item.amount <= amount) {
            amount -= item.amount;
            inventory.setItem(slot, undefined);
        } else {
            // ⚠️ Clone the item and set new amount properly
            const reducedItem = item.clone();
            reducedItem.amount = item.amount - amount;
            inventory.setItem(slot, reducedItem);
            amount = 0;
        }

        if (amount <= 0) break;
    }
}

function showSellMenu(player) {
    const inventory = player.getComponent("minecraft:inventory").container;
    const moneyObjective = world.scoreboard.getObjective("Money");

    const items = [
        { type: "minecraft:cobblestone", name: "Cobblestone", displayName: "§lCobblestone", price: 6 },
        { type: "minecraft:flint", name: "Flint", displayName: "§lFlint", price: 40 },
        { type: "minecraft:coal", name: "Coal", displayName: "§lCoal", price: 10 },
        { type: "minecraft:iron_ingot", name: "Iron Ingot", displayName: "§l§fIron Ingot", price: 26 },
        { type: "minecraft:raw_iron", name: "Raw Iron", displayName: "§lRaw Iron", price: 12 },
        { type: "minecraft:gold_ingot", name: "Gold Ingot", displayName: "§l§eGold Ingot", price: 27 },
        { type: "minecraft:raw_gold", name: "Raw Gold", displayName: "§l§6Raw Gold", price: 13 },
        { type: "minecraft:lapis_lazuli", name: "Lapis Lazuli", displayName: "§l§9Lapis Lazuli", price: 2 },
        { type: "minecraft:redstone", name: "Redstone", displayName: "§l§cRedstone", price: 11 },
        { type: "minecraft:copper_ingot", name: "Copper Ingot", displayName: "§l§6Copper Ingot", price: 25 },
        { type: "minecraft:raw_copper", name: "Raw Copper", displayName: "§lRaw Copper", price: 11 },
        { type: "minecraft:emerald", name: "Emerald", displayName: "§l§aEmerald", price: 18 },
        { type: "minecraft:diamond", name: "Diamond", displayName: "§l§bDiamond", price: 19 },
        { type: "minecraft:quartz", name: "Quartz", displayName: "§l§fQuartz", price: 6 },
        { type: "minecraft:gold_nugget", name: "Gold Nugget", displayName: "§l§eGold Nugget", price: 3 },
        { type: "minecraft:netherite_scrap", name: "Netherite Scrap", displayName: "§l§8Netherite Scrap", price: 180 },
        { type: "minecraft:ancient_debris", name: "Ancient Debris", displayName: "§l§7Ancient Debris", price: 120 },
        { type: "minecraft:obsidian", name: "Obsidian", displayName: "§l§5Obsidian", price: 160 }
    ];

    const inventoryCounts = {};
    let totalSellable = 0;
    for (let slot = 0; slot < inventory.size; slot++) {
        const item = inventory.getItem(slot);
        if (!item) continue;
        inventoryCounts[item.typeId] = (inventoryCounts[item.typeId] || 0) + item.amount;
    }
    for (const item of items) {
        totalSellable += inventoryCounts[item.type] ?? 0;
    }

    if (totalSellable === 0) {
        player.sendMessage("§cYou don't have any sellable items.");
        player.playSound("note.bass");
        return;
    }

    const form = new ModalFormData()
        .title("§lMinerals Sell")
        .dropdown("§7Select a mode", [
            "§aManual Sell (Use sliders)",
            `§cSell All (${totalSellable})`
        ])
        const priceInfo = items.map(i => `§7- ${i.displayName} §f= §a$${i.price}`).join("\n");
const currentMoney = moneyObjective?.getScore(player) ?? 0;

form.slider(
  `§l§6Welcome to Minerals Sell!\n§r§fYou have §a$${currentMoney}§f.\nUse the sliders below to sell specific amounts,\nor choose §c"Sell All"§f above to sell everything.\n\n§l§eSellable Items:\n${priceInfo}`,
  0, 0, 0, 0
);

    for (const item of items) {
        const count = inventoryCounts[item.type] ?? 0;
        form.slider(`${item.displayName} §7(0–${count})`, 0, count, 1, 0);
    }

    form.show(player).then(res => {
        if (res.canceled) return;

        const selectedMode = res.formValues[0];
        const sliderValues = res.formValues.slice(2);

        if (selectedMode === 1) {
            // SELL ALL MODE
            let totalAmount = 0;
            let totalMoney = 0;
            let summaryLines = [];

            for (const item of items) {
                const count = inventoryCounts[item.type] ?? 0;
                if (count > 0) {
                    const earn = count * item.price;
                    totalAmount += count;
                    totalMoney += earn;
                    summaryLines.push(`${item.displayName} §rx §e${count} §7= §a$${earn}§r`);
                }
            }

            const confirm = new MessageFormData()
    .title("§lConfirm Sell All")
    .body(`You're selling:\n\n${summaryLines.join("\n")}\n\n§l§fTotal: §a§l$${totalMoney}§r`)
    .button1("§cCancel")      // Cancel as button 1 (index 0)
    .button2("§aConfirm");    // Confirm as button 2 (index 1)

confirm.show(player).then(confirmRes => {
    if (confirmRes.selection !== 1) {  // Confirm now at index 1
        player.sendMessage("§cSell cancelled.");
        player.playSound("note.bass");
        return;
    }

                for (const item of items) {
                    const count = inventoryCounts[item.type] ?? 0;
                    if (count > 0) removeItems(player, item.type, count);
                }

                if (moneyObjective) {
                    const current = moneyObjective.getScore(player) ?? 0;
                    moneyObjective.setScore(player, current + totalMoney);
                }

                player.sendMessage(`§gYou sold ${totalAmount} items for §a$${totalMoney}`);
                player.playSound("random.orb");
            });

        } else {
            // MANUAL SLIDER MODE
            let totalAmount = 0;
            let totalMoney = 0;
            let summaryLines = [];

            for (let i = 0; i < sliderValues.length; i++) {
                const amount = sliderValues[i];
                const item = items[i];
                if (amount > 0) {
                    const earn = amount * item.price;
                    totalAmount += amount;
                    totalMoney += earn;
                    summaryLines.push(`${item.displayName} §rx §e${amount} §7= §a$${earn}§r`);
                }
            }

            // ✅ If player selected nothing to sell
            if (totalAmount === 0) {
                player.sendMessage("§cNothing selected to sell!");
                player.playSound("note.bass");
                quickmenu(player) 
                return;
            }

            const confirm = new MessageFormData()
    .title("§lConfirm Sale")
    .body(`You're selling:\n\n${summaryLines.join("\n")}\n\n§l§fTotal: §a§l$${totalMoney}§r`)
    .button1("§cCancel")    // Cancel is button 1 (index 0)
    .button2("§aConfirm");  // Confirm is button 2 (index 1)

confirm.show(player).then(confirmRes => {
    if (confirmRes.selection !== 1) {  // Confirm is index 1 now
        player.sendMessage("§cSell cancelled.");
        player.playSound("note.bass");
        quickmenu(player);
        return;
    }

                for (let i = 0; i < sliderValues.length; i++) {
                    const amountToRemove = sliderValues[i];
                    if (amountToRemove > 0) {
                        removeItems(player, items[i].type, amountToRemove);
                    }
                }

                if (moneyObjective) {
                    const current = moneyObjective.getScore(player) ?? 0;
                    moneyObjective.setScore(player, current + totalMoney);
                }

                player.sendMessage(`§gYou sold ${totalAmount} items for §a$${totalMoney}`);
                player.playSound("random.orb");
                quickmenu(player) 
            });
        }
    });
}
    
    
    function shopui(player) {
    new ActionFormData()
        .title('§lShop')
        .body('Choose an option below!')
        .button('Tools\n§r§7[ Click to View ]', "textures/items/iron_pickaxe")
        .button('Weapons\n§r§7[ Click to View ]', "textures/items/iron_sword")
        .button('Armors\n§r§7[ Click to View ]', "textures/items/iron_chestplate")
        .button('Armor Trims\n§r§7[ Click to View ]', "textures/items/wayfinder_armor_trim_smithing_template")
        .button('Projectiles\n§r§7[ Click to View ]', "textures/items/bow_standby")
        .button('Healings\n§r§7[ Click to View ]', "textures/ui/heart")
        .button('Foods\n§r§7[ Click to View ]', "textures/items/apple")
        .button('Other Items\n§r§7[ Click to View ]', "textures/items/chest")
        .button('Music Disc\n§r§7[ Click to View ]', "textures/items/music_disc_13")
        .button('§l§cBack', "textures/ui/arrow_left")
        .show(player).then(r => {
            if (r.selection == 0) tools(player);
            if (r.selection == 1) weapons(player);
            if (r.selection == 2) armors(player);
            if (r.selection == 3) armortrim(player);
            if (r.selection == 4) projectiles(player);
            if (r.selection == 5) healings(player);
            if (r.selection == 6) foods(player);
            if (r.selection == 7) others(player);
            if (r.selection == 8) musicDiscShop(player);
            if (r.selection == 9) quickmenu(player);
        });
}

function musicDiscShop(player) {
    const tags = player.getTags();
    const rankDiscounts = {
        "gwim:God":       { rank: "GOD", discount: 1.0 },
        "gwim:ElitePlus": { rank: "Elite+", discount: 1.0 },
        "gwim:Elite":     { rank: "Elite", discount: 0.8 },
        "gwim:VIPPlus":   { rank: "VIP+", discount: 0.6 },
        "gwim:VIP":       { rank: "VIP", discount: 0.4 }
    };

    let discount = 0;
    let rankName = "None";
    for (const tag in rankDiscounts) {
        if (tags.includes(tag)) {
            discount = rankDiscounts[tag].discount;
            rankName = rankDiscounts[tag].rank;
            break;
        }
    }

    const prices = [
        800, 850, 900, 950, 1000, 1100, 1150,
        1200, 1250, 1300, 1350, 1400, 1450,
        1500, 1550, 1600, 1650, 1700, 1750,
        1800, 1900
    ];

    const discs = [
        "music_disc_13", "music_disc_cat", "music_disc_blocks", "music_disc_chirp", "music_disc_far",
        "music_disc_mall", "music_disc_mellohi", "music_disc_stal", "music_disc_strad", "music_disc_ward",
        "music_disc_11", "music_disc_wait", "music_disc_pigstep", "music_disc_otherside", "music_disc_5",
        "music_disc_relic", "music_disc_precipice", "music_disc_tears", "music_disc_creator",
        "music_disc_creator_music_box", "music_disc_lava_chicken"
    ];

    const discNames = [
        "13", "Cat", "Blocks", "Chirp", "Far", "Mall", "Mellohi", "Stal", "Strad", "Ward",
        "11", "Wait", "Pigstep", "Otherside", "5", "Relic", "Precipice", "Tears",
        "Creator", "Creator (Music Box)", "Lava Chicken"
    ];

    const discountedPrices = prices.map(p => Math.floor(p * (1 - discount)));
    const moneyObjective = world.scoreboard.getObjective("Money");

    function showForm() {
        const currentMoney = moneyObjective.getScore(player) ?? 0;

        const form = new ActionFormData()
            .title("§lMusic Disc")
            .body(`Choose a Music Disc below!\n§7Your Rank: §b§l${rankName}§r\n§7Discount: §a${Math.floor(discount * 100)}%\n§7Money: §a$${currentMoney}`);

        for (let i = 0; i < discs.length; i++) {
            form.button(`§l${discNames[i]}\n§rPrice = §a$${discountedPrices[i]}`, `textures/items/${discs[i]}`);
        }

        form.button("§l§cBack", "textures/ui/arrow_left");

        form.show(player).then(res => {
            if (res.canceled) return;

            const selection = res.selection;
            if (selection === discs.length) return shopui(player); // back

            const selectedDisc = discs[selection];
            const cost = discountedPrices[selection];
            const displayName = discNames[selection];
            const playerMoney = moneyObjective.getScore(player) ?? 0;

            if (playerMoney >= cost) {
                player.runCommandAsync(`scoreboard players remove @s Money ${cost}`);
                player.runCommandAsync(`give @s ${selectedDisc}`);
                player.sendMessage(`§aMusic Disc "${displayName}" purchased successfully!`);
                player.playSound("random.orb");

                system.runTimeout(() => showForm(), 1);
            } else {
                player.sendMessage("§cNot enough money!");
                player.playSound("note.bass");
            }
        });
    }

    showForm();
}




function tools(player) {
    const tags = player.getTags();
    const rankDiscounts = {
        "gwim:God": { rank: "GOD", discount: 1.0 },
        "gwim:ElitePlus": { rank: "Elite+", discount: 1.0 },
        "gwim:Elite":     { rank: "Elite", discount: 0.8 },
        "gwim:VIPPlus":   { rank: "VIP+", discount: 0.6 },
        "gwim:VIP":       { rank: "VIP", discount: 0.4 }
    };

    let discount = 0;
    let rankName = "None";

    for (const tag in rankDiscounts) {
        if (tags.includes(tag)) {
            discount = rankDiscounts[tag].discount;
            rankName = rankDiscounts[tag].rank;
            break;
        }
    }
    
    // Updated prices and items with axes before shovels
let prices = [
    0, 300, 250, 3800, 25899, // Pickaxes
    15, 280, 220, 3600, 25000, // Axes
    10, 200, 125, 2000, 16000  // Shovels
];

let items = [
    "wooden_pickaxe", "stone_pickaxe", "golden_pickaxe", "iron_pickaxe", "diamond_pickaxe",
    "wooden_axe", "stone_axe", "golden_axe", "iron_axe", "diamond_axe",
    "wooden_shovel", "stone_shovel", "golden_shovel", "iron_shovel", "diamond_shovel"
];

    let discountedPrices = prices.map(p => Math.floor(p * (1 - discount)));

    function showForm() {
        let moneyObjective = world.scoreboard.getObjective("Money");
        let updatedScore = moneyObjective.getScore(player) ?? 0;

        let form = new ActionFormData()
            .title('§lTools')
            .body(`Choose a Tool below!\n§7Your Rank: §b§l${rankName}§r\n§7Discount: §a${Math.floor(discount * 100)}%\n§7Money: §a$${updatedScore}`)
            
            // Pickaxes
            .button(`§lWooden Pickaxe\n§rPrice = §a${discountedPrices[0]}`, "textures/items/wood_pickaxe")
            .button(`§lStone Pickaxe\n§rPrice = §a${discountedPrices[1]}`, "textures/items/stone_pickaxe")
            .button(`§lGolden Pickaxe\n§rPrice = §a${discountedPrices[2]}`, "textures/items/gold_pickaxe")
            .button(`§lIron Pickaxe\n§rPrice = §a${discountedPrices[3]}`, "textures/items/iron_pickaxe")
            .button(`§lDiamond Pickaxe\n§rPrice = §a${discountedPrices[4]}`, "textures/items/diamond_pickaxe")
            
            // Axes
            .button(`§lWooden Axe\n§rPrice = §a${discountedPrices[5]}`, "textures/items/wood_axe")
            .button(`§lStone Axe\n§rPrice = §a${discountedPrices[6]}`, "textures/items/stone_axe")
            .button(`§lGolden Axe\n§rPrice = §a${discountedPrices[7]}`, "textures/items/gold_axe")
            .button(`§lIron Axe\n§rPrice = §a${discountedPrices[8]}`, "textures/items/iron_axe")
            .button(`§lDiamond Axe\n§rPrice = §a${discountedPrices[9]}`, "textures/items/diamond_axe")
            
            // Shovels
            .button(`§lWooden Shovel\n§rPrice = §a${discountedPrices[10]}`, "textures/items/wood_shovel")
            .button(`§lStone Shovel\n§rPrice = §a${discountedPrices[11]}`, "textures/items/stone_shovel")
            .button(`§lGolden Shovel\n§rPrice = §a${discountedPrices[12]}`, "textures/items/gold_shovel")
            .button(`§lIron Shovel\n§rPrice = §a${discountedPrices[13]}`, "textures/items/iron_shovel")
            .button(`§lDiamond Shovel\n§rPrice = §a${discountedPrices[14]}`, "textures/items/diamond_shovel")
            
            .button('§l§cBack', "textures/ui/arrow_left");

        form.show(player).then(response => {
            if (response.canceled) return;

            let selection = response.selection;
            if (selection === 15) return shopui(player); // Back button (now at index 15)

            updatedScore = moneyObjective.getScore(player) ?? 0;
            let itemPrice = discountedPrices[selection];
            let itemName = items[selection];

            let formattedName = itemName.replace(/_/g, ' ')
    .replace(/\bpickaxe\b/gi, 'Pickaxe')
    .replace(/\bshovel\b/gi, 'Shovel')
    .replace(/\baxe\b/gi, 'Axe')
    .split(' ')
    .map(word => word.charAt(0).toUpperCase() + word.slice(1))
    .join(' ');

            if (updatedScore >= itemPrice) {
                player.runCommandAsync(`scoreboard players remove @s Money ${itemPrice}`);
                player.runCommandAsync(`give @s ${itemName} 1`);
                player.sendMessage(`§a${formattedName} Purchased Successfully!`);
                player.playSound("random.orb");

                system.runTimeout(() => showForm(), 1);
            } else {
                player.sendMessage("§cNot enough money!");
                player.playSound("note.bass");
            }
        });
    }

    showForm();
}

function weapons(player) {
    const tags = player.getTags();
    const rankDiscounts = {
        "gwim:God": { rank: "GOD", discount: 1.0 },
        "gwim:ElitePlus": { rank: "Elite+", discount: 1.0 },
        "gwim:Elite":     { rank: "Elite", discount: 0.8 },
        "gwim:VIPPlus":   { rank: "VIP+", discount: 0.6 },
        "gwim:VIP":       { rank: "VIP", discount: 0.4 }
    };

    let discount = 0;
    let rankName = "None";

    for (const tag in rankDiscounts) {
        if (tags.includes(tag)) {
            discount = rankDiscounts[tag].discount;
            rankName = rankDiscounts[tag].rank;
            break;
        }
    }

    let prices = [0, 285, 230, 4100, 26000, 51000]; // Removed netherite sword
    let items = [
        "wooden_sword", "stone_sword", "golden_sword", "iron_sword", "diamond_sword", "mace"
    ];
    let discountedPrices = prices.map(p => Math.floor(p * (1 - discount)));

    function showForm() {
        let moneyObjective = world.scoreboard.getObjective("Money");
        let updatedScore = moneyObjective.getScore(player) ?? 0;

        let form = new ActionFormData()
            .title('§lWeapons')
            .body(`Choose a Weapon below!\n§7Your Rank: §b§l${rankName}§r\n§7Discount: §a${Math.floor(discount * 100)}%\n§7Money: §a$${updatedScore}`)
            .button(`§lWooden Sword\n§rPrice = §a${discountedPrices[0]}`, "textures/items/wood_sword")
            .button(`§lStone Sword\n§rPrice = §a${discountedPrices[1]}`, "textures/items/stone_sword")
            .button(`§lGolden Sword\n§rPrice = §a${discountedPrices[2]}`, "textures/items/gold_sword")
            .button(`§lIron Sword\n§rPrice = §a${discountedPrices[3]}`, "textures/items/iron_sword")
            .button(`§lDiamond Sword\n§rPrice = §a${discountedPrices[4]}`, "textures/items/diamond_sword")
            .button(`§lMace\n§rPrice = §a${discountedPrices[5]}`, "textures/items/mace")
            .button('§l§cBack', "textures/ui/arrow_left");

        form.show(player).then(response => {
            if (response.canceled) return;

            let selection = response.selection;
            if (selection === 6) return shopui(player); // Back button (new index)

            let itemPrice = discountedPrices[selection];
            let itemName = items[selection];

            let formattedName = itemName.replace('_', ' ').replace('sword', 'Sword').replace('mace', 'Mace');
            formattedName = formattedName.split(' ').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(' ');

            updatedScore = moneyObjective.getScore(player) ?? 0;

            if (updatedScore >= itemPrice) {
                player.runCommandAsync(`scoreboard players remove @s Money ${itemPrice}`);
                player.runCommandAsync(`give @s ${itemName} 1`);
                player.sendMessage(`§a${formattedName} Purchased Successfully!`);
                player.playSound("random.orb");
                system.runTimeout(() => showForm(), 1);
            } else {
                player.sendMessage("§cNot enough money!");
                player.playSound("note.bass");
            }
        });
    }

    showForm();
}

function armors(player) {
    const tags = player.getTags();
    const rankDiscounts = {
        "gwim:God": { rank: "GOD", discount: 1.0 },
        "gwim:ElitePlus": { rank: "Elite+", discount: 1.0 },
        "gwim:Elite":     { rank: "Elite", discount: 0.8 },
        "gwim:VIPPlus":   { rank: "VIP+", discount: 0.6 },
        "gwim:VIP":       { rank: "VIP", discount: 0.4 }
    };

    let discount = 0;
    let rankName = "None";

    for (const tag in rankDiscounts) {
        if (tags.includes(tag)) {
            discount = rankDiscounts[tag].discount;
            rankName = rankDiscounts[tag].rank;
            break;
        }
    }

    let prices = [
        0, 0, 0, 0, 950, 7480, 9699, 8300, 7000, 
        570, 698, 610, 500, 31100, 36000, 35525, 30999
    ];
    let items = [
        "leather_helmet", "leather_chestplate", "leather_leggings", "leather_boots",
        "turtle_helmet", "iron_helmet", "iron_chestplate", "iron_leggings", "iron_boots",
        "golden_helmet", "golden_chestplate", "golden_leggings", "golden_boots",
        "diamond_helmet", "diamond_chestplate", "diamond_leggings", "diamond_boots"
    ];

    let discountedPrices = prices.map(p => Math.floor(p * (1 - discount)));

    function showForm() {
        let moneyObjective = world.scoreboard.getObjective("Money");
        let updatedScore = moneyObjective.getScore(player) ?? 0;

        let form = new ActionFormData()
            .title('§lArmors')
            .body(`Choose an Armor piece below!\n§7Your Rank: §b§l${rankName}§r\n§7Discount: §a${Math.floor(discount * 100)}%\n§7Money: §a$${updatedScore}`)
            .button(`§lLeather Helmet\n§rPrice = §a${discountedPrices[0]}`, "textures/items/leather_helmet")
            .button(`§lLeather Chestplate\n§rPrice = §a${discountedPrices[1]}`, "textures/items/leather_chestplate")
            .button(`§lLeather Leggings\n§rPrice = §a${discountedPrices[2]}`, "textures/items/leather_leggings")
            .button(`§lLeather Boots\n§rPrice = §a${discountedPrices[3]}`, "textures/items/leather_boots")
            .button(`§lTurtle Helmet\n§rPrice = §a${discountedPrices[4]}`, "textures/items/turtle_helmet")
            .button(`§lIron Helmet\n§rPrice = §a${discountedPrices[5]}`, "textures/items/iron_helmet")
            .button(`§lIron Chestplate\n§rPrice = §a${discountedPrices[6]}`, "textures/items/iron_chestplate")
            .button(`§lIron Leggings\n§rPrice = §a${discountedPrices[7]}`, "textures/items/iron_leggings")
            .button(`§lIron Boots\n§rPrice = §a${discountedPrices[8]}`, "textures/items/iron_boots")
            .button(`§lGolden Helmet\n§rPrice = §a${discountedPrices[9]}`, "textures/items/gold_helmet")
            .button(`§lGolden Chestplate\n§rPrice = §a${discountedPrices[10]}`, "textures/items/gold_chestplate")
            .button(`§lGolden Leggings\n§rPrice = §a${discountedPrices[11]}`, "textures/items/gold_leggings")
            .button(`§lGolden Boots\n§rPrice = §a${discountedPrices[12]}`, "textures/items/gold_boots")
            .button(`§lDiamond Helmet\n§rPrice = §a${discountedPrices[13]}`, "textures/items/diamond_helmet")
            .button(`§lDiamond Chestplate\n§rPrice = §a${discountedPrices[14]}`, "textures/items/diamond_chestplate")
            .button(`§lDiamond Leggings\n§rPrice = §a${discountedPrices[15]}`, "textures/items/diamond_leggings")
            .button(`§lDiamond Boots\n§rPrice = §a${discountedPrices[16]}`, "textures/items/diamond_boots")
            .button('§l§cBack', "textures/ui/arrow_left");

        form.show(player).then(response => {
            if (response.canceled) return;

            let selection = response.selection;
            if (selection === 17) return shopui(player); // Back button (new index)

            let itemPrice = discountedPrices[selection];
            let itemName = items[selection];
            let formattedName = itemName.replace('_', ' ').replace('helmet', 'Helmet')
                .replace('chestplate', 'Chestplate').replace('leggings', 'Leggings')
                .replace('boots', 'Boots');
            formattedName = formattedName.split(' ').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(' ');

            if (updatedScore >= itemPrice) {
                player.runCommandAsync(`scoreboard players remove @s Money ${itemPrice}`);
                player.runCommandAsync(`give @s ${itemName} 1`);
                player.sendMessage(`§a${formattedName} Purchased Successfully!`);
                player.playSound("random.orb");
                system.runTimeout(() => showForm(), 1);
            } else {
                player.sendMessage("§cNot enough money!");
                player.playSound("note.bass");
            }
        });
    }

    showForm();
}


function projectiles(player) {
    const tags = player.getTags();
    const rankDiscounts = {
    	"gwim:God": { rank: "GOD", discount: 1.0 },
        "gwim:ElitePlus": { rank: "Elite+", discount: 1.0 },
        "gwim:Elite":     { rank: "Elite", discount: 0.8 },
        "gwim:VIPPlus":   { rank: "VIP+", discount: 0.6 },
        "gwim:VIP":       { rank: "VIP", discount: 0.4 }
    };

    let discount = 0;
    let rankName = "None";

    for (const tag in rankDiscounts) {
        if (tags.includes(tag)) {
            discount = rankDiscounts[tag].discount;
            rankName = rankDiscounts[tag].rank;
            break;
        }
    }

    let prices = [6500, 5000, 60, 250, 100, 21899, 160, 80];
    let items = [
        "bow 1",
        "crossbow 1",
        "arrow 4",
        "fireball 6",
        "firework_rocket 6",
        "trident 1",
        "wind_charge 6",
        "snowball 8"
    ];

    let discountedPrices = prices.map(p => Math.floor(p * (1 - discount)));

    function showForm() {
        let moneyObjective = world.scoreboard.getObjective("Money");
        let updatedScore = moneyObjective.getScore(player) ?? 0;

        let form = new ActionFormData()
            .title('§lProjectiles')
            .body(`Choose a projectile item below!\n§7Your Rank: §l§b${rankName}§r\n§7Discount: §a${Math.floor(discount * 100)}%\n§7Money: §a$${updatedScore}`)
            .button(`§lBow\n§rPrice = §a${discountedPrices[0]}`, "textures/items/bow_standby")
            .button(`§lCrossbow\n§rPrice = §a${discountedPrices[1]}`, "textures/items/crossbow_standby")
            .button(`§l4 Arrows\n§rPrice = §a${discountedPrices[2]}`, "textures/items/arrow")
            .button(`§l6 Fireballs\n§rPrice = §a${discountedPrices[3]}`, "textures/items/fireball")
            .button(`§l6 Firework Rockets\n§rPrice = §a${discountedPrices[4]}`, "textures/items/firework_rocket")
            .button(`§lTrident\n§rPrice = §a${discountedPrices[5]}`, "textures/items/trident")
            .button(`§l6 Wind Charges\n§rPrice = §a${discountedPrices[6]}`, "textures/items/wind_charge")
            .button(`§l8 Snowballs\n§rPrice = §a${discountedPrices[7]}`, "textures/items/snowball")
            .button('§l§cBack', "textures/ui/arrow_left");

        form.show(player).then(response => {
            if (response.canceled) return;

            let selection = response.selection;
            if (selection === 8) return shopui(player); // Back button

            updatedScore = moneyObjective.getScore(player) ?? 0;

            let itemPrice = discountedPrices[selection];
            let itemData = items[selection];
            let [item, quantity] = itemData.split(' ');
            quantity = parseInt(quantity);

            let formattedName = item.replace(/_/g, ' ').replace(/\b\w/g, char => char.toUpperCase());
            let successMessage = quantity > 1 ? `${quantity} ${formattedName}s` : `${formattedName}`;

            if (updatedScore >= itemPrice) {
                player.runCommandAsync(`scoreboard players remove @s Money ${itemPrice}`);
                player.runCommandAsync(`give @s ${item} ${quantity}`);
                player.sendMessage(`§a${successMessage} Purchased Successfully!`);
                player.playSound("random.orb");

                system.runTimeout(() => showForm(), 1);
            } else {
                player.sendMessage("§cNot enough money!");
                player.playSound("note.bass");
            }
        });
    }

    showForm(); // Call function to show UI
}


function healings(player) {
    const tags = player.getTags();
    const rankDiscounts = {
    	"gwim:God": { rank: "GOD", discount: 1.0 },
        "gwim:ElitePlus": { rank: "Elite+", discount: 1.0 },
        "gwim:Elite":     { rank: "Elite", discount: 0.8 },
        "gwim:VIPPlus":   { rank: "VIP+", discount: 0.6 },
        "gwim:VIP":       { rank: "VIP", discount: 0.4 }
    };

    let discount = 0;
    let rankName = "None";

    for (const tag in rankDiscounts) {
        if (tags.includes(tag)) {
            discount = rankDiscounts[tag].discount;
            rankName = rankDiscounts[tag].rank;
            break;
        }
    }

    let prices = [
        200, 250, 100, 200, 130, 110,
        5879, 22990, 23540
    ];
    let items = [
        "potion 1 22", "potion 1 30", "potion 1 16", "potion 1 33", "potion 1 13", "potion 1 41",
        "golden_apple 4", "enchanted_golden_apple 2", "totem_of_undying 2"
    ];
    let discountedPrices = prices.map(p => Math.floor(p * (1 - discount)));

    let potionNames = {
        "22": "Instant Health Potion",
        "30": "Regeneration Potion",
        "16": "Swiftness Potion",
        "33": "Strength Potion",
        "13": "Fire Resistance Potion",
        "41": "Slow Falling Potion"
    };

    function showForm() {
        let moneyObjective = world.scoreboard.getObjective("Money");
        let updatedScore = moneyObjective.getScore(player) ?? 0;

        let form = new ActionFormData()
            .title('§lHealings')
            .body(`Choose a healing item below!\n§7Your Rank: §b§l${rankName}§r\n§7Discount: §a${Math.floor(discount * 100)}%\n§7Money: §a$${updatedScore}`)
            .button(`§lInstant Health Potion\n§rPrice = §a${discountedPrices[0]}`, "textures/items/potion_bottle_heal")
            .button(`§lRegeneration Potion\n§rPrice = §a${discountedPrices[1]}`, "textures/items/potion_bottle_regeneration")
            .button(`§lSwiftness Potion\n§rPrice = §a${discountedPrices[2]}`, "textures/items/potion_bottle_speed")
            .button(`§lStrength Potion\n§rPrice = §a${discountedPrices[3]}`, "textures/items/potion_bottle_strength")
            .button(`§lFire Resistance Potion\n§rPrice = §a${discountedPrices[4]}`, "textures/items/potion_bottle_fire_resistance")
            .button(`§lSlow Falling Potion\n§rPrice = §a${discountedPrices[5]}`, "textures/items/potion_bottle_slow_falling")
            .button(`§l4 Golden Apples\n§rPrice = §a${discountedPrices[6]}`, "textures/items/apple_golden")
            .button(`§l2 Notch Apples\n§rPrice = §a${discountedPrices[7]}`, "textures/items/enchanted_golden_apple")
            .button(`§l2 Totems of Undying\n§rPrice = §a${discountedPrices[8]}`, "textures/items/totem")
            .button('§l§cBack', "textures/ui/arrow_left");

        form.show(player).then(response => {
            if (response.canceled) return;

            let selection = response.selection;
            if (selection === 9) return shopui(player); // Back button

            updatedScore = moneyObjective.getScore(player) ?? 0;

            let itemPrice = discountedPrices[selection];
            let itemData = items[selection];

            let [item, quantity, potionEffect] = itemData.split(' ');
            quantity = parseInt(quantity, 10);

            let formattedName = item === "potion"
                ? potionNames[potionEffect] ?? "Unknown Potion"
                : item.replace(/_/g, ' ').replace(/\b\w/g, char => char.toUpperCase());

            let successMessage = quantity > 1 ? `${quantity} ${formattedName}s` : `${formattedName}`;

            if (updatedScore >= itemPrice) {
                player.runCommandAsync(`scoreboard players remove @s Money ${itemPrice}`);
                if (item === "potion") {
                    player.runCommandAsync(`give @s potion ${quantity} ${potionEffect}`);
                } else {
                    player.runCommandAsync(`give @s ${item} ${quantity}`);
                }
                player.sendMessage(`§a${successMessage} Purchased Successfully!`);
                player.playSound("random.orb");

                system.runTimeout(() => showForm(), 1);
            } else {
                player.sendMessage("§cNot enough money!");
                player.playSound("note.bass");
            }
        });
    }

    showForm(); // Call function to show UI
}


function foods(player) {
    const tags = player.getTags();
    const rankDiscounts = {
    	"gwim:God": { rank: "GOD", discount: 1.0 },
        "gwim:ElitePlus": { rank: "Elite+", discount: 1.0 },
        "gwim:Elite":     { rank: "Elite", discount: 0.8 },
        "gwim:VIPPlus":   { rank: "VIP+", discount: 0.6 },
        "gwim:VIP":       { rank: "VIP", discount: 0.4 }
    };

    let discount = 0;
    let rankName = "None";

    for (const tag in rankDiscounts) {
        if (tags.includes(tag)) {
            discount = rankDiscounts[tag].discount;
            rankName = rankDiscounts[tag].rank;
            break;
        }
    }

    let prices = [
        0, 5, 10, 15, 25, 35, 50,
        75, 80, 10, 15, 130, 150, 140, 25, 110, 50
    ];
    let items = [
        "dried_kelp 16",
        "glow_berries 8",
        "bread 8",
        "baked_potato 6",
        "cooked_chicken 10",
        "cooked_mutton 12",
        "cooked_porkchop 1",
        "cooked_beef 15", 
        "cooked_rabbit 15", 
        "beetroot_soup 2", 
        "rabbit_stew 2",
        "pumpkin_pie 8", 
        "golden_carrot 10",
        "cooked_cod 12",  
        "mushroom_stew 2",   
        "cooked_salmon 16",    
        "cookie 10"  
    ];
    let discountedPrices = prices.map(p => Math.floor(p * (1 - discount)));

    function showForm() {
        let moneyObjective = world.scoreboard.getObjective("Money");
        let updatedScore = moneyObjective.getScore(player) ?? 0;

        let form = new ActionFormData()
            .title('§lFoods')
            .body(`Choose food items below!\n§7Your Rank: §b§l${rankName}§r\n§7Discount: §a${Math.floor(discount * 100)}%\n§7Money: §a$${updatedScore}`)
            .button(`§l16 Dried Kelp\n§rPrice = §a${discountedPrices[0]}`, "textures/items/dried_kelp")
            .button(`§l8 Glow Berries\n§rPrice = §a${discountedPrices[1]}`, "textures/items/glow_berries")  
            .button(`§l8 Bread\n§rPrice = §a${discountedPrices[2]}`, "textures/items/bread")
            .button(`§l6 Baked Potatoes\n§rPrice = §a${discountedPrices[3]}`, "textures/items/potato_baked")
            .button(`§l10 Cooked Chicken\n§rPrice = §a${discountedPrices[4]}`, "textures/items/chicken_cooked")
            .button(`§l12 Cooked Mutton\n§rPrice = §a${discountedPrices[5]}`, "textures/items/mutton_cooked")
            .button(`§l1 Cooked Porkchop\n§rPrice = §a${discountedPrices[6]}`, "textures/items/porkchop_cooked")
            .button(`§l15 Cooked Beef\n§rPrice = §a${discountedPrices[7]}`, "textures/items/beef_cooked")
            .button(`§l15 Cooked Rabbit\n§rPrice = §a${discountedPrices[8]}`, "textures/items/rabbit_cooked")
            .button(`§l2 Beetroot Soup\n§rPrice = §a${discountedPrices[9]}`, "textures/items/beetroot_soup")
            .button(`§l2 Rabbit Stew\n§rPrice = §a${discountedPrices[10]}`, "textures/items/rabbit_stew")
            .button(`§l8 Pumpkin Pie\n§rPrice = §a${discountedPrices[11]}`, "textures/items/pumpkin_pie")
            .button(`§l10 Golden Carrots\n§rPrice = §a${discountedPrices[12]}`, "textures/items/carrot_golden")
            .button(`§l12 Cooked Cod\n§rPrice = §a${discountedPrices[13]}`, "textures/items/fish_cooked")  
            .button(`§l2 Mushroom Stew\n§rPrice = §a${discountedPrices[14]}`, "textures/items/mushroom_stew")  
            .button(`§l16 Cooked Salmon\n§rPrice = §a${discountedPrices[15]}`, "textures/items/fish_salmon_cooked")  
            .button(`§l10 Cookies\n§rPrice = §a${discountedPrices[16]}`, "textures/items/cookie")  
            .button('§l§cBack', "textures/ui/arrow_left");

        form.show(player).then(response => {
            if (response.canceled) return;

            let selection = response.selection;
            if (selection === 17) return shopui(player); // Back button

            updatedScore = moneyObjective.getScore(player) ?? 0;

            let itemPrice = discountedPrices[selection];
            let itemData = items[selection];

            let [item, quantity] = itemData.split(' ');
            quantity = parseInt(quantity, 10);

            let formattedName = item.replace(/_/g, ' ').replace(/\b\w/g, char => char.toUpperCase());
            let successMessage = `${quantity} ${formattedName}${quantity > 1 ? 's' : ''}`;

            if (updatedScore >= itemPrice) {
                player.runCommandAsync(`scoreboard players remove @s Money ${itemPrice}`);
                player.runCommandAsync(`give @s ${item} ${quantity}`);
                player.sendMessage(`§a${successMessage} Purchased Successfully!`);
                player.playSound("random.orb");

                system.runTimeout(() => showForm(), 1);
            } else {
                player.sendMessage("§cNot enough money!");
                player.playSound("note.bass");
            }
        });
    }

    showForm(); // Call function to show UI
}


function others(player) {
    const tags = player.getTags();
    const rankDiscounts = {
    	"gwim:God": { rank: "GOD", discount: 1.0 },
        "gwim:ElitePlus": { rank: "Elite+", discount: 1.0 },
        "gwim:Elite":     { rank: "Elite", discount: 0.8 },
        "gwim:VIPPlus":   { rank: "VIP+", discount: 0.6 },
        "gwim:VIP":       { rank: "VIP", discount: 0.4 }
    };

    let discount = 0;
    let rankName = "None";

    for (const tag in rankDiscounts) {
        if (tags.includes(tag)) {
            discount = rankDiscounts[tag].discount;
            rankName = rankDiscounts[tag].rank;
            break;
        }
    }

    let prices = [
        1000, 2000, 1250, 18000, 32, 37500, 100, 300, 3500,
        16, 100, 350
    ];

    let items = [
        "compass 1",
        "pa:plot 1", // Plot Management placeholder
        "shield 1",
        "netherite_ingot 1",
        "torch 16",
        "elytra 1",
        "firework_rocket 6",
        "bundle 1",
        "shulker_box 1",
        "experience_bottle 8",
        "spyglass 1",
        "fishing_rod 1"
    ];

    let discountedPrices = prices.map(p => Math.floor(p * (1 - discount)));

    function showForm() {
        let moneyObjective = world.scoreboard.getObjective("Money");
        let updatedScore = moneyObjective.getScore(player) ?? 0;

        let form = new ActionFormData()
            .title('§lOther Items')
            .body(`Choose an item below!\n§7Your Rank: §b§l${rankName}§r\n§7Discount: §a${Math.floor(discount * 100)}%\n§7Money: §a$${updatedScore}`)
            .button(`§lQuick Teleporter\n§rPrice = §a${discountedPrices[0]}`, "textures/items/compass_item")
            .button(`§lPlot Management\n§rPrice = §a${discountedPrices[1]}`, "textures/items/pa_plot")
            .button(`§lShield\n§rPrice = §a${discountedPrices[2]}`, "textures/items/shield")
            .button(`§lNetherite Ingot\n§rPrice = §a${discountedPrices[3]}`, "textures/items/netherite_ingot")
            .button(`§l16 Torch\n§rPrice = §a${discountedPrices[4]}`, "textures/blocks/torch_on")
            .button(`§lElytra\n§rPrice = §a${discountedPrices[5]}`, "textures/items/elytra")
            .button(`§l6 Firework Rockets\n§rPrice = §a${discountedPrices[6]}`, "textures/items/firework_rocket")
            .button(`§lBundle\n§rPrice = §a${discountedPrices[7]}`, "textures/items/bundle")
            .button(`§lShulker Box\n§rPrice = §a${discountedPrices[8]}`, "textures/items/shulker_box")
            .button(`§l8 XP Bottles\n§rPrice = §a${discountedPrices[9]}`, "textures/items/experience_bottle")
            .button(`§lSpyglass\n§rPrice = §a${discountedPrices[10]}`, "textures/items/spyglass")
            .button(`§lFishing Rod\n§rPrice = §a${discountedPrices[11]}`, "textures/items/fishing_rod_uncast")
            .button('§l§cBack', "textures/ui/arrow_left");

        form.show(player).then(response => {
            if (response.canceled) return;

            let selection = response.selection;
            if (selection === 12) return shopui(player); // Back button

            updatedScore = moneyObjective.getScore(player) ?? 0;

            let itemPrice = discountedPrices[selection];
            let itemData = items[selection];

            let [item, quantity] = itemData.split(' ');
            quantity = parseInt(quantity, 10);

            const formattedName = item === "pa:plot" 
    ? "Plot Management" 
    : item.replace(/_/g, ' ').split(' ')
        .map(word => word.charAt(0).toUpperCase() + word.slice(1))
        .join(' ');
            const successMessage = quantity > 1 ? `${quantity} ${formattedName}s` : `${formattedName}`;

            if (updatedScore >= itemPrice) {
                player.runCommandAsync(`scoreboard players remove @s Money ${itemPrice}`);
                player.runCommandAsync(`give @s ${item} ${quantity}`);
                player.sendMessage(`§a${successMessage} Purchased Successfully!`);
                player.playSound("random.orb");

                system.runTimeout(() => showForm(), 1);
            } else {
                player.sendMessage("§cNot enough money!");
                player.playSound("mob.villager.no");
            }
        });
    }

    showForm(); // Call function to show UI
}

function armortrim(player) {
    const tags = player.getTags();
    const rankDiscounts = {
    	"gwim:God": { rank: "GOD", discount: 1.0 },
        "gwim:ElitePlus": { rank: "Elite+", discount: 1.0 },
        "gwim:Elite":     { rank: "Elite", discount: 0.8 },
        "gwim:VIPPlus":   { rank: "VIP+", discount: 0.6 },
        "gwim:VIP":       { rank: "VIP", discount: 0.4 }
    };

    let discount = 0;
    let rankName = "None";

    for (const tag in rankDiscounts) {
        if (tags.includes(tag)) {
            discount = rankDiscounts[tag].discount;
            rankName = rankDiscounts[tag].rank;
            break;
        }
    }

    let prices = Array(17).fill(2000);
    let items = [
        "netherite_upgrade_smithing_template 1",
        "wayfinder_armor_trim_smithing_template 1",
        "shaper_armor_trim_smithing_template 1",
        "host_armor_trim_smithing_template 1",
        "raiser_armor_trim_smithing_template 1",
        "silence_armor_trim_smithing_template 1",
        "sentry_armor_trim_smithing_template 1",
        "dune_armor_trim_smithing_template 1",
        "coast_armor_trim_smithing_template 1",
        "wild_armor_trim_smithing_template 1",
        "ward_armor_trim_smithing_template 1",
        "vex_armor_trim_smithing_template 1",
        "tide_armor_trim_smithing_template 1",
        "snout_armor_trim_smithing_template 1",
        "spire_armor_trim_smithing_template 1",
        "rib_armor_trim_smithing_template 1",
        "eye_armor_trim_smithing_template 1"
    ];

    let discountedPrices = prices.map(p => Math.floor(p * (1 - discount)));

    function showForm() {
        let moneyObjective = world.scoreboard.getObjective("Money");
        let updatedScore = moneyObjective.getScore(player) ?? 0;

        let form = new ActionFormData()
            .title('§lArmor Trims')
            .body(`Choose an Armor trim!\n§7Your Rank: §b§l${rankName}§r\n§7Discount: §a${Math.floor(discount * 100)}%\n§7Money: §a$${updatedScore}`)
            .button(`§lNetherite Upgrade\n§rPrice = §a${discountedPrices[0]}`, "textures/items/netherite_upgrade_smithing_template")
            .button(`§lWayfinder Armor Trim\n§rPrice = §a${discountedPrices[1]}`, "textures/items/wayfinder_armor_trim_smithing_template")
            .button(`§lShaper Armor Trim\n§rPrice = §a${discountedPrices[2]}`, "textures/items/shaper_armor_trim_smithing_template")
            .button(`§lHost Armor Trim\n§rPrice = §a${discountedPrices[3]}`, "textures/items/host_armor_trim_smithing_template")
            .button(`§lRaiser Armor Trim\n§rPrice = §a${discountedPrices[4]}`, "textures/items/raiser_armor_trim_smithing_template")
            .button(`§lSilence Armor Trim\n§rPrice = §a${discountedPrices[5]}`, "textures/items/silence_armor_trim_smithing_template")
            .button(`§lSentry Armor Trim\n§rPrice = §a${discountedPrices[6]}`, "textures/items/sentry_armor_trim_smithing_template")
            .button(`§lDune Armor Trim\n§rPrice = §a${discountedPrices[7]}`, "textures/items/dune_armor_trim_smithing_template")
            .button(`§lCoast Armor Trim\n§rPrice = §a${discountedPrices[8]}`, "textures/items/coast_armor_trim_smithing_template")
            .button(`§lWild Armor Trim\n§rPrice = §a${discountedPrices[9]}`, "textures/items/wild_armor_trim_smithing_template")
            .button(`§lWard Armor Trim\n§rPrice = §a${discountedPrices[10]}`, "textures/items/ward_armor_trim_smithing_template")
            .button(`§lVex Armor Trim\n§rPrice = §a${discountedPrices[11]}`, "textures/items/vex_armor_trim_smithing_template")
            .button(`§lTide Armor Trim\n§rPrice = §a${discountedPrices[12]}`, "textures/items/tide_armor_trim_smithing_template")
            .button(`§lSnout Armor Trim\n§rPrice = §a${discountedPrices[13]}`, "textures/items/snout_armor_trim_smithing_template")
            .button(`§lSpire Armor Trim\n§rPrice = §a${discountedPrices[14]}`, "textures/items/spire_armor_trim_smithing_template")
            .button(`§lRib Armor Trim\n§rPrice = §a${discountedPrices[15]}`, "textures/items/rib_armor_trim_smithing_template")
            .button(`§lEye Armor Trim\n§rPrice = §a${discountedPrices[16]}`, "textures/items/eye_armor_trim_smithing_template")
            .button('§l§cBack', "textures/ui/arrow_left");

        form.show(player).then(response => {
            if (response.canceled) return;

            let selection = response.selection;
            if (selection === 17) return shopui(player); // Back button

            updatedScore = moneyObjective.getScore(player) ?? 0;

            let itemPrice = discountedPrices[selection];
            let itemData = items[selection];

            let [item, quantity] = itemData.split(' ');
            quantity = parseInt(quantity, 10);

            let formattedName = item.replace(/_/g, ' ').replace(/\b\w/g, char => char.toUpperCase());
            let successMessage = `${formattedName}${quantity > 1 ? 's' : ''}`;

            if (updatedScore >= itemPrice) {
                player.runCommandAsync(`scoreboard players remove @s Money ${itemPrice}`);
                player.runCommandAsync(`give @s ${item} ${quantity}`);
                player.sendMessage(`§a${successMessage} Purchased Successfully!`);
                player.playSound("random.orb");

                system.runTimeout(() => showForm(), 1);
            } else {
                player.sendMessage("§cNot enough money!");
                player.playSound("note.bass");
            }
        });
    }

    showForm(); // Call function to show UI
}
    
    
    function about(player) {
        new ActionFormData()
            .title('§lAbout')
            .body("Choose an option below")
            .button('§cRules\n§r§7[ Click to View ]', "textures/ui/ErrorGlyph")
            .button('§9How to play\n§r§7[ Click to View ]', "textures/ui/blue_info_glyph")
            .button('§eCredits\n§r§7[ Click to View ]', "textures/ui/permissions_op_crown")
            .button('§gChangelog\n§r§7[ Click to View ]', "textures/items/book_writable")
            .button('§l§cBack', "textures/ui/arrow_left")
            .show(player).then(r => {
                if (r.selection == 0) rules(player)
                if (r.selection == 1) howtoplay(player)
                if (r.selection == 2) Credits(player)
                if (r.selection == 3) changelog(player)
                if (r.selection == 4) main(player)
            })
    }
    
    function changelog(player) {
    new ActionFormData()
        .title("§l§gChangelog")
        .body("§eSelect a version to view its changes")
        .button('§c§lBETA 5.0\n§r§7[ Click to View ]', "textures/items/book_writable")
        .button('§c§lBETA 4.0\n§r§7[ Click to View ]', "textures/items/book_writable")
        .button('§c§lBETA 3.0\n§r§7[ Click to View ]', "textures/items/book_writable")
        .button('§l§cBack', "textures/ui/arrow_left")
        .show(player).then(r => {
            if (r.selection == 0) changelogBeta5(player)
            if (r.selection == 1) changelogBeta4(player)
            if (r.selection == 2) changelogBeta3(player)
            if (r.selection == 3) about(player)
        });
}

function changelogBeta5(player) {
    new ActionFormData()
        .title("§lChangelog – BETA 5.0")
        .body(
            `§l§nCHANGELOG§r\n` +
            `§r§eVersion: §cBETA 5.0\n\n` +

            `§l§aNew Features:\n` +
            `§7• New §2Wood Mining Area§7 with §aLumber Merchant§7 (left side of Mining Simulator)\n` +
            `§7• New §bSkyWars!§r\n` +
            `   §7- Mining §cRedstone Ore§7 gives extra hearts (up to 8)\n` +
            `   §7- Redstone regenerates after 9 seconds\n` +
            `   §7- Only §8Andesite§7 can be placed, disappears after 9 seconds (keeps map clean)\n` +
            `§7• §6The Land§7 system updated with 9 plots\n` +
            `   §7- Players can own up to 2 plots at once\n` +
            `   §7- Other players cannot build/break in owned plots\n\n` +

            `§l§eImprovements:\n` +
            `§7• PvE now supports up to §aWave 40\n` +
            `§7• New Kill/Death reward system:\n` +
            `   §7- Every 600 kills: +100k (then increases gradually)\n` +
            `   §7- Every additional 600 kills: +30k bonus\n` +
            `   §7- 50 deaths: -5k | 100 deaths: -8k | 150 deaths: -10k (gradual increase)\n` +
            `§7• Barrier borders added in PvP arena\n` +
            `§7• Anvils added under feet on main BlockDrop map\n` +
            `§7• Server menu improvements + new §aPlot Manager§7 item (Shop → Other Items)\n` +
            `§7• Discounts added for higher ranks in Shop\n` +
            `§7• VIP Minerals sell option in Shop & Sell menu\n` +
            `§7• New §eServer UI textures\n` +
            `§7• Added §6Pressure Plate Boost§7 (Stone & Dark Oak plates)\n` +
            `§7• Added §fFeather Boost§7 (boosts based on where you look)\n` +
            `§7• Fancy Teleporting system added\n` +
            `§7• Killing players now gives §a5k Money§7 each\n` +
            `§7• Durability viewer for tools & armor added\n` +
            `§7• Many more general improvements\n\n` +

            `§l§cFixes:\n` +
            `§7• Restricted block breaking/placing/interaction in protected areas\n` +
            `   (e.g., trapdoors, fence gates, crafting table UIs, etc.)\n` +
            `§7• Fixed PvE bug where spamming start/stop caused glitches\n` +
            `§7• Fixed bug where players could open admin chests in Admin Shop\n` +
            `§7• Fixed bug where teleporting from End sometimes created nether portal in Lobby\n` +
            `§7• Disabled Nether dimension (Quick TP to Overworld instead)\n` +
            `§7• Placed missing border blocks in Admin Shop & PvP Arena\n` +
            `§7• Ranks now update correctly after heavy rejoins\n` +
            `§7• Parkour checkpoint now uses dynamic properties instead of /spawnpoint\n` +
            `§7• BlockDrop now supports max 8 players\n` +
            `§7• Many more bug fixes\n\n` +

            `§l§9Technical Changes:\n` +
            `§7• Removed excessive §bDimension.getEntities§7 calls (FPS boost)\n` +
            `§7• Replaced tags.includes with §btags.delete§7 (better performance)\n` +
            `§7• Optimized §bworld.getPlayers§7 → now cached every 10 ticks (faster scripts)\n` +
            `§7• Used dynamic properties for saving ranked players' particle toggles\n\n` +

            `§l§aThanks for playing and enjoy BETA 5.0!`
        )
        .button('§l§cBack', "textures/ui/arrow_left")
        .show(player).then(r => {
            if (r.selection === 0) changelog(player);
        });
}

function changelogBeta4(player) {
    new ActionFormData()
        .title("§lChangelog – BETA 4.0")
        .body(
            `§l§nCHANGELOG§r\n` +
            `§r§eCurrent Version: §cBETA 4.0\n\n` +

            `§l§aNew Features:\n` +
            `§7• Totally a new lobby (big lobby added)\n` +
            `§7• Added RANKS NPC in the lobby with new rank system\n` +
            `§7• Warrior rank: Strength V and Resistance III permanently\n` +
            `§7• Healer rank: Regeneration V permanently\n` +
            `§7• Miner rank: Haste V permanently\n` +
            `§7• New PvP area added (coming fully soon)\n` +
            `§7• New PvE area in cave-like dungeons (script-based with custom AI & loot)\n` +
            `§7• Shulker Box Place added\n` +
            `§7• Relaxing Park added\n` +
            `§7• Relaxing Place removed (will return in a future update)\n` +
            `§7• New Admin Shop area\n` +
            `§7• New cave-like Mining Area 2\n` +
            `§7• Improved Enchanting Room and Smelting Room\n` +
            `§7• New NPCs with better functions\n\n` +

            `§l§eImprovements:\n` +
            `§7• Parkour checkpoint now uses dynamic properties\n` +
            `§7• BowWars slightly improved\n` +
            `§7• BlockDrop fully changed, now Hive-like using dynamic properties\n` +
            `§7• Server GUI improved with new player info buttons\n` +
            `§7• Scoreboard display system (can hide/unhide via settings)\n` +
            `§7• Gamerules, weather, and time now saved properly\n` +
            `§7• Kills/deaths count properly with fire aspect/flame\n` +
            `§7• Small changes in School & Neighborhood\n` +
            `§7• Slightly improved VIP Zone\n\n` +

            `§l§cFixes:\n` +
            `§7• End reward requires dragon kill (script-based)\n` +
            `§7• Land disabled due to bugs (back in future)\n` +
            `§7• Admin OP shop removed, replaced by OP Enchanter NPC\n` +
            `§7• Several bug fixes\n\n` +

            `§l§aThanks for playing and enjoy BETA 4.0!`
        )
        .button('§l§cBack', "textures/ui/arrow_left")
        .show(player).then(r => {
            if (r.selection === 0) changelog(player);
        });
}

function changelogBeta3(player) {
    new ActionFormData()
        .title("§lChangelog – BETA 3.0")
        .body(
            `§l§nCHANGELOG§r\n` +
            `§r§eVersion: §cBETA 3.0\n\n` +

            `§l§aNew Features:\n` +
            `§7• Lobby updated\n` +
            `§7• SkyWars lobby added\n\n` +

            `§l§eImprovements:\n` +
            `§7• Skyblock mine expanded to 3×3\n` +
            `§7• Renamed mining areas\n` +
            `§7• Fixed bank manager teleportation\n` +
            `§7• Land improvements\n` +
            `§7• New PvE arena + system improvements\n` +
            `§7• Trees added to Relaxing Park border\n` +
            `§7• PvP system enhancements\n` +
            `§7• Selling is now 5× faster\n` +
            `§7• Server menu improved\n` +
            `§7• AFK detection in selling room\n` +
            `§7• Shop/sell prices adjusted\n\n` +

            `§l§cFixes:\n` +
            `§7• Removed info popup\n` +
            `§7• General bug fixes\n\n` +

            `§l§aThanks for playing and enjoy BETA 3.0!`
        )
        .button('§l§cBack', "textures/ui/arrow_left")
        .show(player).then(r => {
            if (r.selection === 0) changelog(player);
        });
}
    
    function rules(player) {
    new ActionFormData()
        .title('§l§cServer Rules')
        .body(
            `§l§cMUST READ - SERVER RULES\n` +
            `§r§7Violating any of these rules may result in §4ban, mute, or restrictions.\n\n` +

            `§l§eRule 1: §r§fCrafting Tables are §cNOT allowed§f.\n` +
            `§7Use only the server's official systems to obtain items.\n\n` +

            `§l§eRule 2: §r§fNo §cgriefing§f or §chacking§f.\n` +
            `§7Cheating or destroying others' builds = §4instant ban§7.\n\n` +

            `§l§eRule 3: §r§fNo §ctoxic behavior§f.\n` +
            `§7Spamming, trolling, and offensive language are punishable.\n\n` +

            `§l§eRule 4: §r§fAlways §brespect§f others.\n` +
            `§7Be kind, no bullying or hate speech.\n\n` +

            `§l§eRule 5: §r§fNo §cstealing§f.\n` +
            `§7Do not take items from other players or chests without permission.\n\n` +

            `§l§eRule 6: §r§fDo not exploit bugs or glitches.\n` +
            `§7Report any exploits to staff immediately.\n\n` +

            `§l§eRule 7: §r§fFollow staff instructions at all times.\n` +
            `§7Disrespecting staff can lead to a ban.\n\n` +

            `§l§eRule 8: §r§fNo alt accounts to bypass bans or gain unfair advantages.\n\n` +

            `§r§cThese rules apply everywhere — §lno exceptions.§r\n`
        )
        .button('§l§cBack', 'textures/ui/arrow_left')
        .show(player).then(r => {
            if (r.selection === 0) about(player);
        });
}

    function howtoplay(player) {
    new ActionFormData()
        .title("§l§9How to play")
        .body(
            `§l§n§bHOW TO PLAY§r\n\n` +

            `§r§7Welcome to the world of §aMining Simulator§7!\n` +
            `§7Here, your mission is to become the §6§lRichest Miner Alive!§r\n\n` +

            `§l§6▶ STARTING OFF ◀§r\n` +
            `§r• Get a free §2Wooden Pickaxe §rfrom §aThe Merchant§r.\n` +
            `• Also grab a §6Wooden Axe§r to start chopping trees!\n` +
            `• Collect valuable logs: §6Oak§r, §8Dark Oak§r, §2Spruce§r, §fBirch§r,\n  §ePale Oak§r, §aJungle§r, §cAcacia§r, §dCherry§r.\n` +
            `• Head into the §aMining Area§r and start digging for ores!\n` +
            `• Collect valuable ores: §7Cobblestone§r, §8Coal§r, §fIron§r, §6Gold§r,\n  §1Lapis§r, §4Redstone§r, §9Flint§r, §8Copper§r, §2Emerald§r,\n  §bDiamond§r, §0Obsidian§r, and §5Ancient Debris§r.\n\n` +

            `§l§e▶ SELL & UPGRADE ◀§r\n` +
            `§r• Sell ores & logs to the §eMineral Merchant §rfor money.\n` +
            `• Use your earnings to §aUpgrade Tools§r, §bBuy Armor§r,\n  §dPotions§r, §cFood§r, and more in the §aThe Merchant§r.\n\n` +

            `§l§3▶ MINI GAMES ◀§r\n` +
            `§r§d• PVP     • PVE     • Parkour\n` +
            `• BlockDrop     • SkyWars     • BowWars\n` +
            `• §5The End §7- §rKill the Ender Dragon for special rewards\n` +
            `§8(More mini-games coming soon!)\n\n` +

            `§l§9▶ PLACES TO EXPLORE ◀§r\n` +
            `§7• §fGarbage Bank§8 – Retrieve cleared items\n` +
            `§7• §fShulker Box Area§8 – Organize your gear\n` +
            `§7• §fRelaxing Park§8 – Take a break with friends\n` +
            `§7• §fSchool & Neighborhood§8 – Explore secrets\n` +
            `§7• §fThe Land§8 – Buy land and build your dream base\n` +
            `§7• §6VIP Zone§8 – Exclusive area for VIP players\n\n` +

            `§l§aReady to begin your journey? Let’s dig in!`
        )
        .button('§l§cBack', "textures/ui/arrow_left")
        .show(player).then(r => {
            if (r.selection === 0) about(player);
        });
}

    function Credits(player) {
    new ActionFormData()
        .title("§l§eCredits")
        .body(
            // Header
            `§l§nCREDITS§r\n\n` +

            // Developer section
            `§l§dDeveloper & Architect:\n` +
            `§r §bFly Sakib\n\n` +

            // Builders section
            `§l§9Builders:\n` +
            `§r §aAdwin1st\n` +
            ` §aPiste9642\n\n` +
            ` §aBluewwie\n\n` +

            // Tools & Technology
            `§l§aBuilt With:\n` +
            `§r §7• Minecraft Bedrock Scripting API\n` +
            ` §7• Custom Behavior Packs\n` +
            ` §7• Hundreds of Command Blocks\n` +
            ` §7• Creative Vision & Late Nights\n\n` +

            // Special Thanks
            `§l§eSpecial Thanks To:\n` +
            `§r §bCommunity Testers & Players\n` +
            ` §bFeedback Contributors\n` +
            ` §bFriends & Family\n\n` +

            // Acknowledgments
            `§l§6Acknowledgments:\n` +
            `§r §7- Everyone who offered ideas\n` +
            ` §7- Those patient with testing phases\n` +
            ` §7- Anyone who supported the project\n\n` +

            // Final note
            `§l§cThank You For Playing!\n` +
            `§r§bYour adventures power this world.\n` +
            `§r§bKeep mining, exploring, and having fun!`
        )
        .button('§l§cBack', "textures/ui/arrow_left")
        .show(player).then(r => {
            if (r.selection === 0) about(player);
        });
}


function QuickTeleports(player) {
    	const over = world.getDimension("minecraft:overworld");
        new ActionFormData()
            .title("§l§eQuick Teleporter")
            .body('Choose where you wanna Go!')
            .button('§l§aMINING SIMULATOR\n§r§7[ Click to Teleport ]', "textures/items/diamond_pickaxe")
            .button('§l§aMINING AREA 2\n§r§7[ Click to Teleport ]', "textures/items/iron_pickaxe")
            .button('§l§bMINI §3GAMES\n§r§7[ Click to View ]', "textures/items/iron_sword")
            .button('§l§cPLACES\n§r§7[ Click to View ]', "textures/ui/relaxing")
            .button('§l§6Lobby\n§r§7[ Click to Teleport ]', "textures/ui/world_glyph_color_2x")
            .show(player).then(r => {
                if (r.selection == 0) {
                    over.runCommandAsync(`tp "${player.name}" 4000 5 -4000 facing 3999 5 -4000`).then(() => {
        system.runTimeout(() => {
            player.runCommandAsync(`particle minecraft:knockback_roar_particle ~ ~ ~`);
            player.runCommandAsync(`clearspawnpoint @s`);
            player.addEffect("blindness", 20, {
  amplifier: 0,
  showParticles: false
});
            player.playSound("mob.endermen.portal");
        }, 1); // delay by 1 tick (~50ms)
    });
                }
                if (r.selection == 1) {
                    over.runCommandAsync(`tp "${player.name}" 3000 6 -3000 facing 2999 6 -3000`).then(() => {
        system.runTimeout(() => {
            player.runCommandAsync(`particle minecraft:knockback_roar_particle ~ ~ ~`);
            player.runCommandAsync(`clearspawnpoint @s`);
            player.addEffect("blindness", 20, {
  amplifier: 0,
  showParticles: false
});
            player.playSound("mob.endermen.portal");
        }, 1); // delay by 1 tick (~50ms)
    });
                }
                if (r.selection == 2) MINIGAMES(player)
                if (r.selection == 3) PLACES(player)
                if (r.selection == 4) {
                    over.runCommandAsync(`tp "${player.name}" 0 200 0 facing 0 200 1`).then(() => {
        system.runTimeout(() => {
            player.runCommandAsync(`particle minecraft:knockback_roar_particle ~ ~ ~`);
            player.runCommandAsync(`clearspawnpoint @s`);
            player.addEffect("blindness", 20, {
  amplifier: 0,
  showParticles: false
});
            player.playSound("item.trident.return");
        }, 1); // delay by 1 tick (~50ms)
    });
                }
            })
    }



    function MINIGAMES(player) {
    	const over = world.getDimension("minecraft:overworld");
    new ActionFormData()
        .title("§lMINI GAMES")
        .body('Choose where you wanna Teleport!')
        .button('§l§bP§eV§bP\n§r§7[ Click to Teleport ]', "textures/ui/pvp")
        .button('§l§bP§eV§cE\n§r§7[ Click to Teleport ]', "textures/ui/pve")
        .button('§l§bTHE END\n§r§7[ Click to Teleport ]', "textures/ui/end")
        .button('§l§5Parkour\n§r§7[ Click to Teleport ]', "textures/ui/parkour")
        .button('§l§cBow§bWars\n§r§7[ Click to Teleport ]', "textures/items/bow_standby")
        .button('§l§dBlock§6Drop §l§c[BETA]\n§r§7[ Click to Teleport ]', "textures/ui/blockdrop")
        .button('§l§bSky§eWars\n§r§7[ Click to Teleport ]', "textures/ui/skywars")
        .button('§l§dBlock§bParty\n§l§c[Not Available]')
        .button('§g§lDeathRun\n§l§c[Not Available]')
        .button('§l§fGravity\n§l§c[Not Available]')
        .button('§l§cBack', "textures/ui/arrow_left")
        .show(player).then(r => {
            let currentPos = player.location;

            if (r.selection == 0) {
    const locations = [
        { x: -993, y: 31, z: 1007 },
        { x: -1007, y: 31, z: 1007 },
        { x: -1007, y: 31, z: 993 },
        { x: -993, y: 31, z: 993 }
    ];

    // Pick a random location
    const loc = locations[Math.floor(Math.random() * locations.length)];

    over.runCommandAsync(`tp "${player.name}" ${loc.x} ${loc.y} ${loc.z}`).then(() => {
        system.runTimeout(() => {
            player.runCommandAsync(`particle minecraft:knockback_roar_particle ~ ~ ~`);
            player.runCommandAsync(`clearspawnpoint @s`);
            player.addEffect("blindness", 20, {
                amplifier: 0,
                showParticles: false
            });
            player.playSound("mob.endermen.portal");
        }, 1); // delay by 1 tick
    });
}
            if (r.selection == 1) {
    over.runCommandAsync(`tp "${player.name}" 1000 5 -1000 facing 1001 5 -1000`).then(() => {
        system.runTimeout(() => {
            player.runCommandAsync(`particle minecraft:knockback_roar_particle ~ ~ ~`);
            player.runCommandAsync(`spawnpoint @s 1000 5 -1000`);
            player.addEffect("blindness", 20, {
                amplifier: 0,
                showParticles: false
            });
            player.playSound("mob.endermen.portal");
        }, 1); // delay by 1 tick (~50ms)
    });
}
            if (r.selection == 2) {
                const end = world.getDimension("minecraft:the_end");
                      end.runCommandAsync(`tp "${player.name}" 18 63 0`).then(() => {
        system.runTimeout(() => {
            player.runCommandAsync(`particle minecraft:knockback_roar_particle ~ ~ ~`);
            player.runCommandAsync(`clearspawnpoint @s`);
            player.addEffect("blindness", 20, {
  amplifier: 0,
  showParticles: false
});
            player.playSound("mob.endermen.portal");
        }, 1); // delay by 1 tick (~50ms)
    });
            }
            if (r.selection == 3) {
                over.runCommandAsync(`tp "${player.name}" -2000 5 -2000 facing -2000 5 -1999`).then(() => {
        system.runTimeout(() => {
            player.runCommandAsync(`particle minecraft:knockback_roar_particle ~ ~ ~`);
            player.runCommandAsync(`clearspawnpoint @s`);
            player.addEffect("blindness", 20, {
  amplifier: 0,
  showParticles: false
});
            player.playSound("mob.endermen.portal");
        }, 1); // delay by 1 tick (~50ms)
    });
            }
            if (r.selection == 4) {
                over.runCommandAsync(`tp "${player.name}" -3000 5 3000 facing -2999 5 3000`).then(() => {
        system.runTimeout(() => {
            player.runCommandAsync(`particle minecraft:knockback_roar_particle ~ ~ ~`);
            player.runCommandAsync(`clearspawnpoint @s`);
            player.addEffect("blindness", 20, {
  amplifier: 0,
  showParticles: false
});
            player.playSound("mob.endermen.portal");
        }, 1); // delay by 1 tick (~50ms)
    });
            }
            if (r.selection == 5) {
                over.runCommandAsync(`tp "${player.name}" 2000 5 -2000 facing 2000 5 -1999`).then(() => {
        system.runTimeout(() => {
            player.runCommandAsync(`particle minecraft:knockback_roar_particle ~ ~ ~`);
            player.runCommandAsync(`clearspawnpoint @s`);
            player.addEffect("blindness", 20, {
  amplifier: 0,
  showParticles: false
});
            player.playSound("mob.endermen.portal");
        }, 1); // delay by 1 tick (~50ms)
    });
            }
            if (r.selection == 6) {
    // === SkyWars random teleport ===
    const skywarsSpawns = [
        { x: 4974, y: 62, z: 4943 },
        { x: 4943, y: 62, z: 4970 },
        { x: 4935, y: 62, z: 4998 },
        { x: 4943, y: 62, z: 5026 },
        { x: 4970, y: 62, z: 5057 },
        { x: 4998, y: 62, z: 5065 },
        { x: 5026, y: 62, z: 5057 },
        { x: 5057, y: 62, z: 5030 },
        { x: 5065, y: 62, z: 5002 },
        { x: 5057, y: 62, z: 4974 },
        { x: 5030, y: 62, z: 4943 },
        { x: 5002, y: 62, z: 4935 },
    ];

    // Pick random spawn
    const spawn = skywarsSpawns[Math.floor(Math.random() * skywarsSpawns.length)];

    // Teleport facing the middle (5000 60 5000)
    over.runCommandAsync(`tp "${player.name}" ${spawn.x} ${spawn.y} ${spawn.z} facing 5000 60 5000`).then(() => {
        system.runTimeout(() => {
            player.runCommandAsync(`particle minecraft:knockback_roar_particle ~ ~ ~`);
            player.runCommandAsync(`clearspawnpoint @s`);
            player.addEffect("blindness", 20, {
                amplifier: 0,
                showParticles: false
            });
            player.playSound("mob.endermen.portal");
        }, 1); // delay by 1 tick (~50ms)
    });
}
            if (r.selection == 10) QuickTeleports(player)
        })
}

    function PLACES(player) {
    	const over = world.getDimension("minecraft:overworld");
    new ActionFormData()
        .title("§lPLACES")
        .body('Choose where you wanna Teleport!')
        .button('§l§8GarBage Bank\n§r§7[ Click to Teleport ]', "textures/ui/icon_trash")
        .button('§l§dShulker Box Place\n§r§7[ Click to Teleport ]', "textures/items/shulker_box")
        .button('§l§bAdmin Shop\n§r§7[ Click to Teleport ]', "textures/ui/admin")
        .button('§l§3School §e& §bNeighbourhood\n§r§7[ Click to Teleport ]', "textures/ui/school")
        .button('§l§eRelaxing Park\n§r§7[ Click to Teleport ]', "textures/ui/relaxing")
        .button('§l§eV.I.P §gZone\n§r§7[ Click to Teleport ]', "textures/ui/filledStar")
        .button('§l§tThe Land §e[NEW]\n§r§7[ Click to Teleport ]', "textures/ui/welcome")
        .button('§l§cBack', "textures/ui/arrow_left")
        .show(player).then(r => {
            let currentPos = player.location;

            if (r.selection == 0) {
                over.runCommandAsync(`tp "${player.name}" 1000 5 1000 facing 1000 5 1001`).then(() => {
        system.runTimeout(() => {
            player.runCommandAsync(`particle minecraft:knockback_roar_particle ~ ~ ~`);
            player.runCommandAsync(`clearspawnpoint @s`);
            player.addEffect("blindness", 20, {
  amplifier: 0,
  showParticles: false
});
            player.playSound("mob.endermen.portal");
        }, 1); // delay by 1 tick (~50ms)
    });
            }
            if (r.selection == 1) {
                over.runCommandAsync(`tp "${player.name}" -5000 4 -5000 facing -5000 4 -4999`).then(() => {
        system.runTimeout(() => {
            player.runCommandAsync(`particle minecraft:knockback_roar_particle ~ ~ ~`);
            player.runCommandAsync(`clearspawnpoint @s`);
            player.addEffect("blindness", 20, {
  amplifier: 0,
  showParticles: false
});
            player.playSound("mob.endermen.portal");
        }, 1); // delay by 1 tick (~50ms)
    });
            }
            if (r.selection == 2) {
                over.runCommandAsync(`tp "${player.name}" 3000 4 3000 facing 3000 4 2999`).then(() => {
        system.runTimeout(() => {
            player.runCommandAsync(`particle minecraft:knockback_roar_particle ~ ~ ~`);
            player.runCommandAsync(`clearspawnpoint @s`);
            player.addEffect("blindness", 20, {
  amplifier: 0,
  showParticles: false
});
            player.playSound("mob.endermen.portal");
        }, 1); // delay by 1 tick (~50ms)
    });
            }
            if (r.selection == 3) {
                over.runCommandAsync(`tp "${player.name}" -1967 4 1876 facing -1966 4 1876`).then(() => {
        system.runTimeout(() => {
            player.runCommandAsync(`particle minecraft:knockback_roar_particle ~ ~ ~`);
            player.runCommandAsync(`clearspawnpoint @s`);
            player.addEffect("blindness", 20, {
  amplifier: 0,
  showParticles: false
});
            player.playSound("mob.endermen.portal");
        }, 1); // delay by 1 tick (~50ms)
    });
            }
            if (r.selection == 4) {
                over.runCommandAsync(`tp "${player.name}" -3000 4 -3000 facing -3000 4 -3001`).then(() => {
        system.runTimeout(() => {
            player.runCommandAsync(`particle minecraft:knockback_roar_particle ~ ~ ~`);
            player.runCommandAsync(`clearspawnpoint @s`);
            player.addEffect("blindness", 20, {
  amplifier: 0,
  showParticles: false
});
            player.playSound("mob.endermen.portal");
        }, 1); // delay by 1 tick (~50ms)
    });
            }
            if (r.selection == 5) {
                handleTeleportation(player);
            }
            if (r.selection == 6) {
    over.runCommandAsync(`tp "${player.name}" 10000 4 9922 facing 10000 4 9921`).then(() => {
        system.runTimeout(() => {
            player.runCommandAsync(`particle minecraft:knockback_roar_particle ~ ~ ~`);
            player.runCommandAsync(`clearspawnpoint @s`);
            player.addEffect("blindness", 20, {
                amplifier: 0,
                showParticles: false
            });
            player.playSound("mob.endermen.portal");
        }, 1); // delay by 1 tick (~50ms)
    });
} // ✅ properly closed

if (r.selection == 7) {
    QuickTeleports(player);
}
})
}

function handleTeleportation(player) {
    try {
        if (
            player.hasTag("gwim:VIP") ||
            player.hasTag("gwim:Admin") ||
            player.hasTag("gwim:Owner") ||
            player.hasTag("gwim:God") ||
            player.hasTag("gwim:VIPPlus") ||
            player.hasTag("gwim:Elite") ||
            player.hasTag("gwim:ElitePlus")
        ) {
            const over = world.getDimension("minecraft:overworld");
            over.runCommandAsync(`tp "${player.name}" 4000 5 4000 facing 4001 5 4000`).then(() => {
        system.runTimeout(() => {
            player.runCommandAsync(`particle minecraft:knockback_roar_particle ~~~`);
            player.runCommandAsync(`clearspawnpoint @s`);
            player.addEffect("blindness", 20, {
  amplifier: 0,
  showParticles: false
});
            player.playSound("mob.endermen.portal");
        }, 1); // delay by 1 tick (~50ms)
    });
        } else {
            player.sendMessage("§cYou need a VIP rank to enter here!");
            player.playSound("note.bass");
        }
    } catch (error) {
        console.error(error);
    }
}





// === EXCLUSION ZONES ===
const exclusionZones = [
  [835, -60, -1214, 1235, 200, -814],      // Zone 1
  [-910, 4, 919, -1097, 200, 1088],        // Zone 2
  [-2974, 3, 2987, -2936, 20, 3013],       // Zone 3
  [4921, 98, 4921, 5079, 15, 5079],
];

function isInExclusionZone(x, y, z, dimensionId) {
  if (dimensionId === 'minecraft:the_end') return false; // Always blocked in the End
  if (dimensionId !== 'minecraft:overworld') return true; // Always allowed in Nether or others
  return exclusionZones.some(([x1, y1, z1, x2, y2, z2]) =>
    x >= Math.min(x1, x2) && x <= Math.max(x1, x2) &&
    y >= Math.min(y1, y2) && y <= Math.max(y1, y2) &&
    z >= Math.min(z1, z2) && z <= Math.max(z1, z2)
  );
}

// === SHARED ITEM BEHAVIOR ===
function handleItemUse(player, itemId) {
  const { x, y, z } = player.location;
  const dimensionId = player.dimension.id;

  // === Feather Knockback ===
  if (itemId === "minecraft:feather") {
    const dir = player.getViewDirection();
    const mag = Math.sqrt(dir.x * dir.x + dir.y * dir.y + dir.z * dir.z);
    const nx = dir.x / (mag || 1);
    const ny = dir.y / (mag || 1);
    const nz = dir.z / (mag || 1);
    const horizMag = Math.sqrt(nx * nx + nz * nz);
    const normX = nx / (horizMag || 1);
    const normZ = nz / (horizMag || 1);
    const absY = Math.abs(ny);
    const horizontalStrength = 1.2 + (1 - absY) * 2.5;
    const verticalStrength = 0.2 + ny * 1.2;

    system.run(() => {
      try {
        player.applyKnockback(normX, normZ, horizontalStrength, verticalStrength);
        player.playSound("mob.enderdragon.flap");
        player.runCommandAsync("clear @s[m=!c] minecraft:feather 0 1");
      } catch (e) {
        console.warn("Feather launch failed:", e);
      }
    });
    return true;
  }

  // === Fire Charge ===
  if (itemId === "minecraft:fire_charge") {
    if (!isInExclusionZone(x, y, z, dimensionId)) {
      player.sendMessage("§cYou can't shoot fireballs here!");
      player.runCommandAsync("playsound note.bass @s");
      return true;
    }
    system.run(() => {
      player.runCommand("clear @s[m=!c] fire_charge 0 1");
      player.runCommand("playsound mob.ghast.fireball @a ~~~ 1");
      const dir = player.getViewDirection();
      const loc = { x: x + dir.x * 1.5, y: y + 1 + dir.y * 1.5, z: z + dir.z * 1.5 };
      const fireball = player.dimension.spawnEntity("minecraft:fireball", loc);
      fireball.applyImpulse(dir);
    });
    return true;
  }

  // === Wither Skull Stick ===
  if (itemId === "minecraft:stick") {
    if (!isInExclusionZone(x, y, z, dimensionId)) {
      player.sendMessage("§cYou can't shoot wither skulls here!");
      player.runCommandAsync("playsound note.bass @s");
      return true;
    }
    system.run(() => {
      player.runCommand("clear @s[m=!c] stick 0 0");
      player.runCommand("playsound mob.wither.shoot @a ~~~ 1");
      const dir = player.getViewDirection();
      const loc = { x: x + dir.x * 1.5, y: y + 1 + dir.y * 1.5, z: z + dir.z * 1.5 };
      const skullType = Math.random() < 0.5 ? "minecraft:wither_skull" : "minecraft:wither_skull_dangerous";
      const skull = player.dimension.spawnEntity(skullType, loc);
      skull.applyImpulse(dir);
    });
    return true;
  }

  // === Compass TP ===
  if (itemId === "minecraft:compass") {
    system.run(() => QuickTeleports(player));
    return true;
  }
  
  // === Lobby trigger ===
  if (itemId === "pa:plot") {
    system.run(() => openPlotManagement(player));
    return true;
  }

  // === Lobby trigger ===
  if (itemId === "pa:lobby") {
    system.run(() => main(player));
    return true;
  }

  return false; // No match
}

// === EVENT: itemUse (air) ===
world.beforeEvents.itemUse.subscribe(event => {
  const player = event.source;
  const item = event.itemStack;
  if (!player || !item) return;

  const itemId = item.typeId;
  const { x, y, z } = player.location;
  const dimensionId = player.dimension.id;


  // === Allow Ender Pearls only inside the specific zone ===
  if (itemId === "minecraft:ender_pearl") {
    const [x1, y1, z1, x2, y2, z2] = [4921, 98, 4921, 5079, 15, 5079];
    const inZone = x >= Math.min(x1, x2) && x <= Math.max(x1, x2) &&
                   y >= Math.min(y1, y2) && y <= Math.max(y1, y2) &&
                   z >= Math.min(z1, z2) && z <= Math.max(z1, z2);

    if (!inZone) {
      player.sendMessage("§cYou can't use Ender Pearls here!");
      player.runCommandAsync("playsound note.bass @s");
      event.cancel = true;
      return;
    }
  }

  // === Block bows outside exclusion zones ===
  if (itemId.includes("bow")) {
  // ✅ Allow bow always in the End
  if (dimensionId === "minecraft:the_end") return;

  // ❌ Restrict bow in other dimensions unless in allowed zone
  if (!isInExclusionZone(x, y, z, dimensionId)) {
    player.sendMessage("§cYou can't shoot here!");
    player.runCommandAsync("playsound note.bass @s");
    event.cancel = true;
    return;
  }
}

  if (handleItemUse(player, itemId)) event.cancel = true;
});


// =====================
// PLOT LOOKUP
// =====================

export function getPlotIdAtLocation(location) {
  for (let id in PLOTS) {
    const plot = PLOTS[id];
    if (
      location.x >= plot.min.x && location.x <= plot.max.x &&
      location.y >= plot.min.y && location.y <= plot.max.y &&
      location.z >= plot.min.z && location.z <= plot.max.z
    ) return Number(id);
  }
  return null;
}


const PLOTS = {
  1: { min: { x: 9894, y: 1, z: 9933 }, max: { x: 9950, y: 61, z: 9989 } },
  2: { min: { x: 9972, y: 1, z: 9933 }, max: { x: 10028, y: 61, z: 9989 } },
  3: { min: { x: 10050, y: 1, z: 9933 }, max: { x: 10106, y: 61, z: 9989 } },
  4: { min: { x: 9894, y: 1, z: 10011 }, max: { x: 9950, y: 61, z: 10067 } },
  5: { min: { x: 9972, y: 1, z: 10011 }, max: { x: 10028, y: 61, z: 10067 } },
  6: { min: { x: 10050, y: 1, z: 10011 }, max: { x: 10106, y: 61, z: 10067 } },
  7: { min: { x: 9894, y: 1, z: 10089 }, max: { x: 9950, y: 61, z: 10145 } },
  8: { min: { x: 9972, y: 1, z: 10089 }, max: { x: 10028, y: 61, z: 10145 } },
  9: { min: { x: 10050, y: 1, z: 10089 }, max: { x: 10106, y: 61, z: 10145 } },
};

const allowedInteractBlocks = [
  "minecraft:anvil",
  "minecraft:chest",
  "minecraft:trapped_chest",
  "minecraft:ender_chest",
  "minecraft:enchanting_table",
  "minecraft:smithing_table",
  "minecraft:grindstone",
  "minecraft:jukebox",
  "minecraft:blast_furnace",
  "minecraft:lit_blast_furnace",
  "shulker_box", // Partial match
  "door",
  "bell",
  "cake",
  "button"
];

// === PLACE BLOCK CONTROL ===
world.beforeEvents.itemUseOn.subscribe(event => {
  const { itemStack: item, source: player, block } = event;
  if (!player || !block) return;

  const itemId = item?.typeId ?? "";
  const blockId = block.typeId;
  const dimensionId = player.dimension.id;
  
  // ❌ Disable crafting table usage for everyone
  if (blockId === "minecraft:crafting_table") {
    event.cancel = true;
    return;
  }

  if (player.hasTag("gwim:Admin")) return; // Admin bypass

  // Check if inside a plot
const plotId = getPlotIdAtLocation(block.location);
if (plotId) {
    const owner = getOwner(plotId);

    if (player.name === owner) return; // Owner bypass

    // Non-owner blocked
    if (owner) {
        player.sendMessage(`§cPlot §b#${plotId} §cbelongs to §e${owner}§c! You can’t build or interact here.`);
    } else {
        player.sendMessage(`§cPlot §b#${plotId} §cis §eunowned§c! Buy it first before building.`);
    }

    player.runCommandAsync("playsound note.bass @s");
    event.cancel = true;
    return;
}
  
  // ✅ Allow compass/lobby items to go through to handleItemUse logic
  if (
    itemId !== "minecraft:compass" &&
    itemId !== "pa:plot" &&
    itemId !== "pa:lobby" &&
    handleItemUse(player, itemId)
  ) {
    event.cancel = true;
    return;
  }

  // ✅ Special: allow placing andesite in radius 100 around 5000,60,5000
  const allowedAndesiteCenter = { x: 5000, y: 60, z: 5000 };
  const allowedAndesiteRadius = 100;
  const dx = player.location.x - allowedAndesiteCenter.x;
  const dy = player.location.y - allowedAndesiteCenter.y;
  const dz = player.location.z - allowedAndesiteCenter.z;
  if (
    itemId === "minecraft:andesite" &&
    Math.sqrt(dx*dx + dy*dy + dz*dz) <= allowedAndesiteRadius
  ) return;

  // ✅ Always allow placing torches anywhere
  if (
    (
      blockId.includes("pot") ||
      blockId.includes("gate") ||
      blockId.includes("trapdoor") ||
      blockId.includes("frame") ||
      blockId.includes("barrel") ||
      blockId.includes("shelf") ||
      blockId === "minecraft:furnace" ||
      blockId === "minecraft:dropper" ||
      blockId === "minecraft:dispenser" ||
      blockId === "minecraft:crafter"
    ) && itemId.includes("torch")
  ) {
    event.cancel = true;
    return;
  }
  if (itemId.includes("torch")) return;

  if (blockId === "minecraft:bedrock" && itemId.includes("shulker_box")) return;

  // ✅ Allow placing end crystal on bedrock only in End
  if (blockId === "minecraft:bedrock" && itemId === "minecraft:end_crystal" && dimensionId === "minecraft:the_end") return;

  // ✅ Allow placing only if block is in allowed list (excluding trapdoors)
  if (
    allowedInteractBlocks.some(allowed => blockId.includes(allowed)) &&
    !blockId.includes("trapdoor")
  ) return;

  // ❌ Cancel everything else
  event.cancel = true;
});

// === INTERACT WITH BLOCK CONTROL ===
world.beforeEvents.playerInteractWithBlock.subscribe(event => {
  const { player, block, itemStack: item } = event;
  if (!player || !block) return;

  const blockId = block.typeId;
  const itemId = item?.typeId ?? "";
  const dimensionId = player.dimension.id;
  
  // ❌ Disable crafting table usage for everyone
  if (blockId === "minecraft:crafting_table") {
    event.cancel = true;
    return;
  }

  if (player.hasTag("gwim:Admin")) return; // Admin bypass
  
  // Check if inside a plot
const plotId = getPlotIdAtLocation(block.location);
if (plotId) {
    const owner = getOwner(plotId);

    if (player.name === owner) return; // Owner bypass

    // Non-owner blocked
    if (owner) {
        player.sendMessage(`§cPlot §b#${plotId} §cbelongs to §e${owner}§c! You can’t build or interact here.`);
    } else {
        player.sendMessage(`§cPlot §b#${plotId} §cis §eunowned§c! Buy it first before building.`);
    }

    player.runCommandAsync("playsound note.bass @s");
    event.cancel = true;
    return;
}
  
  // ✅ Special: allow placing andesite in radius 100 around 5000,60,5000
  const allowedAndesiteCenter = { x: 5000, y: 60, z: 5000 };
  const allowedAndesiteRadius = 100;
  const dx = player.location.x - allowedAndesiteCenter.x;
  const dy = player.location.y - allowedAndesiteCenter.y;
  const dz = player.location.z - allowedAndesiteCenter.z;
  if (
    itemId === "minecraft:andesite" &&
    Math.sqrt(dx*dx + dy*dy + dz*dz) <= allowedAndesiteRadius
  ) return;
  
  if (
  (
    blockId.includes("pot") ||
    blockId.includes("gate") ||
    blockId.includes("trapdoor") ||
    blockId.includes("frame") ||
    blockId.includes("barrel") ||
    blockId.includes("shelf") ||
    blockId === "minecraft:furnace" ||
    blockId === "minecraft:dropper" ||
    blockId === "minecraft:dispenser" ||
    blockId === "minecraft:crafter"
  ) && itemId.includes("torch")
) {
  event.cancel = true;
  return;
}
  
  if (itemId.includes("torch")) return;

  // ✅ Always allow interacting with any shulker box
  if (blockId === "minecraft:bedrock" && itemId.includes("shulker_box")) return;

  // ✅ Allow interacting with end crystal on bedrock only in End
  if (blockId === "minecraft:bedrock" && itemId === "minecraft:end_crystal" && dimensionId === "minecraft:the_end") return;

  // ✅ Allow interacting only if block is in allowed list
  if (
    allowedInteractBlocks.some(allowed =>
      blockId.includes(allowed)
    ) &&
    !blockId.includes("trapdoor")
  ) return;

  // ❌ Cancel everything else
  event.cancel = true;
});