import { world, system, EntityComponentTypes, StructureRotation, ItemStack } from "@minecraft/server";
// =============================================================================================================================================================================
// ADD-ON SPAWN RULES
// =============================================================================================================================================================================
world.afterEvents.playerSpawn.subscribe((data)=>{
    for (const player of world.getAllPlayers()){
        player.runCommand(`execute as @a[tag=!wonder_pets_joined] run execute positioned as @s run structure load wonder_pets:guide_book ~ ~ ~`);
        player.runCommand(`execute as @a[tag=!wonder_pets_joined] run tag @s add wonder_pets_joined`);
    }
});
world.beforeEvents.playerLeave.subscribe((event)=>{
    world.setDynamicProperty("pd", JSON.stringify(playerData));
});
// =============================================================================================================================================================================
// ERROR MESSAGES
// =============================================================================================================================================================================
// interacting with a useable item but the pet is not tamed yet
//@ts-ignore
world.afterEvents.playerInteractWithEntity.subscribe((event)=>{
    var target = event.target;
    try {
        if (target.matches({
            families: [
                "wonder_pets"
            ]
        }) && target?.getComponent("variant")["value"] == 0) {
            event.player.runCommandAsync(`tellraw @s {\"rawtext\":[{\"translate\":\"hint.wonder_pets.error.not_tamed\"}]}`);
        }
    } catch (e) {}
});
// =============================================================================================================================================================================
// COSMETICS
// =============================================================================================================================================================================
// drop cosmetics on death
world.afterEvents.entityDie.subscribe(({ deadEntity, damageSource })=>{
    //world.sendMessage("death")
    var families = deadEntity.getComponent(EntityComponentTypes.TypeFamily);
    if (families) var isPet = families["hasTypeFamily"]("wonder_pets");
    if (isPet && deadEntity.getProperty('wonder_pets:hat') != undefined) {
        switch(deadEntity.getProperty('wonder_pets:hat')){
            case "top_hat":
                deadEntity.runCommand(`loot spawn ~ ~ ~ loot "wonder/pets/animals/cosmetics/hat_top_hat"`);
                break;
            case "sunglasses":
                deadEntity.runCommand(`loot spawn ~ ~ ~ loot "wonder/pets/animals/cosmetics/hat_sunglasses"`);
                break;
            case "propeller":
                deadEntity.runCommand(`loot spawn ~ ~ ~ loot "wonder/pets/animals/cosmetics/hat_propeller"`);
                break;
            case "dino_cap":
                deadEntity.runCommand(`loot spawn ~ ~ ~ loot "wonder/pets/animals/cosmetics/hat_dino_cap"`);
                break;
            case "baseball_cap":
                deadEntity.runCommand(`loot spawn ~ ~ ~ loot "wonder/pets/animals/cosmetics/hat_baseball_cap"`);
                break;
            case "cupcake_hat":
                deadEntity.runCommand(`loot spawn ~ ~ ~ loot "wonder/pets/animals/cosmetics/hat_cupcake_hat"`);
                break;
            case "bow_pink":
                deadEntity.runCommand(`loot spawn ~ ~ ~ loot "wonder/pets/animals/cosmetics/hat_bow_pink"`);
                break;
            case "bow_green":
                deadEntity.runCommand(`loot spawn ~ ~ ~ loot "wonder/pets/animals/cosmetics/hat_bow_green"`);
                break;
            case "bow_yellow":
                deadEntity.runCommand(`loot spawn ~ ~ ~ loot "wonder/pets/animals/cosmetics/hat_bow_yellow"`);
                break;
            case "crown":
                deadEntity.runCommand(`loot spawn ~ ~ ~ loot "wonder/pets/animals/cosmetics/hat_crown"`);
                break;
            default:
                break;
        }
    }
});
// =============================================================================================================================================================================
// THROWABLES
// =============================================================================================================================================================================
// play sounds when items are thrown
world.afterEvents.itemUse.subscribe((event)=>{
    const player = event.source;
    const item = event.itemStack;
    const cooldown = item.getComponent("minecraft:cooldown");
    if (item.typeId === "wonder_pets:tennis_ball_item" && player.getItemCooldown("wonder_pets_tennis_ball") === cooldown["cooldownTicks"] - 1) {
        player.runCommandAsync("playsound wonder_pets:ball_throw @a[r=30] ~ ~ ~");
    }
    if (item.typeId === "wonder_pets:throwing_stick_item" && player.getItemCooldown("wonder_pets_throwing_stick") === cooldown["cooldownTicks"] - 1) {
        player.runCommandAsync("playsound wonder_pets:stick_throw @a[r=30] ~ ~ ~");
    }
    if (item.typeId.includes("_placer") && item.typeId.includes("wonder_pets:")) {
        usedPlaceableItem(player, item);
    }
});
// =============================================================================================================================================================================
// PLACEABLES
// =============================================================================================================================================================================
system.runInterval(()=>{
    //dismount pets on crouch/jump
    var players = world.getAllPlayers().forEach((player)=>{
        if (player.isJumping || player.isSneaking || player.isInWater) {
            var rideable = player.getComponent(EntityComponentTypes.Rideable);
            //see if any of the riders are wonder pets
            rideable.getRiders().forEach((rider)=>{
                if (rider.typeId.includes("wonder_pets:")) {
                    rider.triggerEvent("wonder_pets:start_ride_cooldown");
                    system.runTimeout(()=>{
                        rideable?.ejectRider(rider);
                        player.playSound("wonder_pets:pet_mount_player");
                        if (playerData[player.id] != undefined && playerData[player.id].riders != undefined) {
                            var riderIndex = playerData[player.id].riders.indexOf(rider.id);
                            if (riderIndex > -1) {
                                playerData[player.id].riders.splice(riderIndex, 1);
                            }
                        }
                    }, 2);
                }
            });
        }
    });
}, 3);
system.runInterval(()=>{
    //pet health
    var entities = world.getDimension("overworld").getEntities({
        families: [
            "wonder_pets"
        ]
    }).concat(world.getDimension("nether").getEntities({
        families: [
            "wonder_pets"
        ]
    }), world.getDimension("the_end").getEntities({
        families: [
            "wonder_pets"
        ]
    }));
    entities.forEach((entity)=>{
        var healthVisible = entity.getProperty("wonder_pets:health_visible");
        if (healthVisible != undefined) {
            var players = world.getDimension(entity.dimension.id).getPlayers({
                maxDistance: 6,
                location: entity.location
            });
            var validFood = false;
            if (players && players.length > 0) {
                for (var player of players){
                    var inventory = player.getComponent(EntityComponentTypes.Inventory);
                    var heldItem = inventory?.container?.getItem(player.selectedSlotIndex);
                    if (heldItem != undefined) {
                        var heldItemId = heldItem.typeId.replace("minecraft:", "");
                        if (heldItemId == "wonder_pets:pet_treat" || heldItemId == "wonder_pets:pet_food") {
                            validFood = true;
                            break;
                        }
                        if (entity.typeId == "wonder_pets:capybara") {
                            var validFoods = [
                                "sugar_cane",
                                "wheat",
                                "melon_slice",
                                "bamboo",
                                "apple"
                            ];
                            if (validFoods.includes(heldItemId)) validFood = true;
                            break;
                        }
                        if (entity.typeId == "wonder_pets:cat") {
                            var validFoods = [
                                "rabbit",
                                "beef",
                                "chicken",
                                "mutton",
                                "tropical_fish",
                                "cod",
                                "salmon",
                                "porkchop",
                                "cooked_beef",
                                "cooked_chicken",
                                "cooked_cod",
                                "cooked_mutton",
                                "cooked_porkchop",
                                "cooked_rabbit",
                                "cooked_salmon"
                            ];
                            if (validFoods.includes(heldItemId)) validFood = true;
                            break;
                        }
                        if (entity.typeId == "wonder_pets:chipmunk") {
                            var validFoods = [
                                "red_mushroom",
                                "brown_mushroom",
                                "melon_seeds",
                                "pumpkin_seeds",
                                "beetroot_seeds",
                                "wheat_seeds",
                                "sweet_berries",
                                "apple"
                            ];
                            if (validFoods.includes(heldItemId)) validFood = true;
                            break;
                        }
                        if (entity.typeId == "wonder_pets:dog") {
                            var validFoods = [
                                "rabbit",
                                "beef",
                                "chicken",
                                "mutton",
                                "tropical_fish",
                                "cod",
                                "salmon",
                                "porkchop",
                                "cooked_beef",
                                "cooked_chicken",
                                "cooked_cod",
                                "cooked_mutton",
                                "cooked_porkchop",
                                "cooked_rabbit",
                                "cooked_salmon",
                                "carrot",
                                "apple",
                                "melon_slice"
                            ];
                            if (validFoods.includes(heldItemId)) validFood = true;
                            break;
                        }
                        if (entity.typeId == "wonder_pets:elephant") {
                            var validFoods = [
                                "stick",
                                "pumpkin",
                                "carrot",
                                "apple",
                                "melon_slice"
                            ];
                            if (validFoods.includes(heldItemId)) validFood = true;
                            break;
                        }
                        if (entity.typeId == "wonder_pets:giraffe") {
                            var validFoods = [
                                "wheat_seeds",
                                "melon_seeds",
                                "pumpkin_seeds",
                                "beetroot_seeds",
                                "stick",
                                "melon_slice",
                                "apple"
                            ];
                            if (validFoods.includes(heldItemId)) validFood = true;
                            break;
                        }
                        if (entity.typeId == "wonder_pets:hamster") {
                            var validFoods = [
                                "carrot",
                                "melon_seeds",
                                "pumpkin_seeds",
                                "beetroot_seeds",
                                "wheat_seeds",
                                "sweet_berries",
                                "apple"
                            ];
                            if (validFoods.includes(heldItemId)) validFood = true;
                            break;
                        }
                        if (entity.typeId == "wonder_pets:hedgehog") {
                            var validFoods = [
                                "rabbit",
                                "beef",
                                "chicken",
                                "mutton",
                                "porkchop",
                                "cooked_beef",
                                "cooked_chicken",
                                "cooked_mutton",
                                "cooked_porkchop",
                                "cooked_rabbit",
                                "carrot",
                                "apple",
                                "melon_slice"
                            ];
                            if (validFoods.includes(heldItemId)) validFood = true;
                            break;
                        }
                        if (entity.typeId == "wonder_pets:hippo") {
                            var validFoods = [
                                "pumpkin",
                                "carrot",
                                "beetroot",
                                "apple",
                                "melon_slice",
                                "kelp"
                            ];
                            if (validFoods.includes(heldItemId)) validFood = true;
                            break;
                        }
                        if (entity.typeId == "wonder_pets:kangaroo") {
                            var validFoods = [
                                "wheat",
                                "dandelion",
                                "poppy",
                                "blue_orchid",
                                "allium",
                                "azure_bluet",
                                "red_tulip",
                                "orange_tulip",
                                "white_tulip",
                                "pink_tulip",
                                "oxeye_daisy",
                                "cornflower",
                                "lily_of_the_valley",
                                "sunflower",
                                "lilac",
                                "rose_bush",
                                "peony",
                                "pink_petals"
                            ];
                            if (validFoods.includes(heldItemId)) validFood = true;
                            break;
                        }
                        if (entity.typeId == "wonder_pets:koala") {
                            var validFoods = [
                                "sugar_cane",
                                "oak_sapling",
                                "jungle_sapling",
                                "birch_sapling",
                                "acacia_sapling",
                                "bamboo_sapling",
                                "cherry_sapling",
                                "spruce_sapling",
                                "dark_oak_sapling",
                                "pale_oak_sapling"
                            ];
                            if (validFoods.includes(heldItemId)) validFood = true;
                            break;
                        }
                        if (entity.typeId == "wonder_pets:lion") {
                            var validFoods = [
                                "rabbit",
                                "beef",
                                "chicken",
                                "mutton",
                                "tropical_fish",
                                "cod",
                                "salmon",
                                "porkchop",
                                "cooked_beef",
                                "cooked_chicken",
                                "cooked_cod",
                                "cooked_mutton",
                                "cooked_porkchop",
                                "cooked_rabbit",
                                "cooked_salmon"
                            ];
                            if (validFoods.includes(heldItemId)) validFood = true;
                            break;
                        }
                        if (entity.typeId == "wonder_pets:meerkat") {
                            var validFoods = [
                                "melon_seeds",
                                "pumpkin_seeds",
                                "beetroot_seeds",
                                "wheat_seeds",
                                "egg",
                                "carrot",
                                "melon_slice",
                                "apple"
                            ];
                            if (validFoods.includes(heldItemId)) validFood = true;
                            break;
                        }
                        if (entity.typeId == "wonder_pets:monkey") {
                            var validFoods = [
                                "melon_seeds",
                                "pumpkin_seeds",
                                "beetroot_seeds",
                                "wheat_seeds",
                                "carrot",
                                "apple",
                                "melon_slice"
                            ];
                            if (validFoods.includes(heldItemId)) validFood = true;
                            break;
                        }
                        if (entity.typeId == "wonder_pets:owl") {
                            var validFoods = [
                                "rabbit",
                                "beef",
                                "chicken",
                                "mutton",
                                "tropical_fish",
                                "cod",
                                "salmon",
                                "porkchop",
                                "cooked_beef",
                                "cooked_chicken",
                                "cooked_cod",
                                "cooked_mutton",
                                "cooked_porkchop",
                                "cooked_rabbit",
                                "cooked_salmon"
                            ];
                            if (validFoods.includes(heldItemId)) validFood = true;
                            break;
                        }
                        if (entity.typeId == "wonder_pets:penguin") {
                            var validFoods = [
                                "tropical_fish",
                                "cod",
                                "salmon",
                                "cooked_cod",
                                "cooked_salmon"
                            ];
                            if (validFoods.includes(heldItemId)) validFood = true;
                            break;
                        }
                        if (entity.typeId == "wonder_pets:platypus") {
                            var validFoods = [
                                "tropical_fish",
                                "cod",
                                "salmon",
                                "cooked_salmon",
                                "cooked_cod"
                            ];
                            if (validFoods.includes(heldItemId)) validFood = true;
                            break;
                        }
                        if (entity.typeId == "wonder_pets:red_panda") {
                            var validFoods = [
                                "sugar_cane",
                                "melon_slice",
                                "bamboo",
                                "apple",
                                "carrot"
                            ];
                            if (validFoods.includes(heldItemId)) validFood = true;
                            break;
                        }
                        if (entity.typeId == "wonder_pets:snow_leopard") {
                            var validFoods = [
                                "rabbit",
                                "beef",
                                "chicken",
                                "mutton",
                                "porkchop",
                                "cooked_beef",
                                "cooked_chicken",
                                "cooked_mutton",
                                "cooked_porkchop",
                                "cooked_rabbit"
                            ];
                            if (validFoods.includes(heldItemId)) validFood = true;
                            break;
                        }
                        if (entity.typeId == "wonder_pets:tiger") {
                            var validFoods = [
                                "rabbit",
                                "beef",
                                "chicken",
                                "mutton",
                                "tropical_fish",
                                "cod",
                                "salmon",
                                "porkchop",
                                "cooked_beef",
                                "cooked_chicken",
                                "cooked_cod",
                                "cooked_mutton",
                                "cooked_porkchop",
                                "cooked_rabbit",
                                "cooked_salmon"
                            ];
                            if (validFoods.includes(heldItemId)) validFood = true;
                            break;
                        }
                        if (entity.typeId == "wonder_pets:unicorn") {
                            var validFoods = [
                                "cookie",
                                "cake",
                                "glow_berries"
                            ];
                            if (validFoods.includes(heldItemId)) validFood = true;
                            break;
                        }
                        if (entity.typeId == "wonder_pets:zebra") {
                            var validFoods = [
                                "stick",
                                "oak_sapling",
                                "jungle_sapling",
                                "birch_sapling",
                                "acacia_sapling",
                                "bamboo_sapling",
                                "cherry_sapling",
                                "spruce_sapling",
                                "dark_oak_sapling",
                                "pale_oak_sapling"
                            ];
                            if (validFoods.includes(heldItemId)) validFood = true;
                            break;
                        }
                        if (validFood) break;
                    }
                }
                if (healthVisible && !validFood) {
                    entity.setProperty("wonder_pets:health_visible", false);
                }
                if (!healthVisible && validFood) {
                    entity.setProperty("wonder_pets:health_visible", true);
                }
            } else {
                entity.setProperty("wonder_pets:health_visible", false);
            }
        }
    });
}, 10);
var playerData = {
};
world.afterEvents.worldInitialize.subscribe((event)=>{
    var savedPlayerData = String(world.getDynamicProperty("pd"));
    if (savedPlayerData != "undefined") {
        playerData = JSON.parse(savedPlayerData);
    }
});
class Placeable {
    constructor(properties){
        this.offset = properties.offset ? sumVector3(properties.offset, {
            x: 0.5,
            y: 1,
            z: 0.5
        }) : {
            x: 0.5,
            y: 1,
            z: 0.5
        };
        this.rotation = properties.rotation ? properties.rotation : 3;
        this.rotationVariants = properties.rotationVariants == undefined ? false : properties.rotationVariants;
        this.buttonAnchor = properties.buttonAnchor ? properties.buttonAnchor : {
            x: 0,
            y: 1,
            z: 3.5
        };
        if (properties.evenOffsetCorrect == undefined) {
            if (properties.mini) {
                this.evenOffsetCorrect = true;
            } else {
                this.evenOffsetCorrect = false;
            }
        } else {
            this.evenOffsetCorrect = properties.evenOffsetCorrect;
        }
        var defaultOffset = {
            x: -6,
            y: -3,
            z: -6
        };
        if (properties.mini) {
            defaultOffset = {
                x: -3,
                y: -3,
                z: -4
            }; //was { x: -3, y: -3, z: -3 };
            if (properties.buttonAnchor == undefined) this.buttonAnchor = {
                x: 0.5,
                y: 1,
                z: 2.5
            };
        }
        this.structureOffset = properties.structureOffset ? sumVector3(properties.structureOffset, defaultOffset) : defaultOffset;
    }
}
var placeables = {
    "cat_tree": new Placeable({
        buttonAnchor: {
            x: -0.5,
            y: 1,
            z: 3.5
        }
    }),
    "cat_house": new Placeable({
        buttonAnchor: {
            x: 0,
            y: 1,
            z: 5.5
        },
        rotationVariants: true
    }),
    "capybara_house": new Placeable({
        buttonAnchor: {
            x: 0,
            y: 1,
            z: 4.5
        }
    }),
    "chipmunk_house": new Placeable({
        buttonAnchor: {
            x: 0,
            y: 1,
            z: 4.5
        },
        rotationVariants: true,
        rotation: 2
    }),
    "dog_house": new Placeable({
        rotationVariants: true
    }),
    "elephant_house": new Placeable({
        rotation: 2
    }),
    "giraffe_house": new Placeable({
        buttonAnchor: {
            x: 0,
            y: 1,
            z: 4.5
        },
        rotation: 2
    }),
    "hamster_house": new Placeable({
        rotationVariants: true
    }),
    "hedgehog_house": new Placeable({
        rotationVariants: true
    }),
    "hippo_house": new Placeable({}),
    "kangaroo_house": new Placeable({
        buttonAnchor: {
            x: 0,
            y: 1,
            z: 4.5
        },
        rotation: 2,
        rotationVariants: true
    }),
    "koala_house": new Placeable({}),
    "lion_house": new Placeable({
        rotationVariants: true
    }),
    "meerkat_house": new Placeable({}),
    "monkey_house": new Placeable({}),
    "owl_house": new Placeable({
        buttonAnchor: {
            x: 0,
            y: 1,
            z: 4.5
        },
        rotation: 1
    }),
    "penguin_house": new Placeable({
        rotation: 1
    }),
    "platypus_house": new Placeable({
        buttonAnchor: {
            x: 0.5,
            y: 1,
            z: 3.5
        }
    }),
    "red_panda_house": new Placeable({
        buttonAnchor: {
            x: 0,
            y: 1,
            z: 5.5
        }
    }),
    "snow_leopard_house": new Placeable({
        rotationVariants: true
    }),
    "tiger_house": new Placeable({
        rotationVariants: true
    }),
    "unicorn_house": new Placeable({}),
    "zebra_house": new Placeable({
        buttonAnchor: {
            x: 0,
            y: 1,
            z: 4.5
        },
        rotation: 2
    }),
    "capybara_mini": new Placeable({
        mini: true
    }),
    "cat_mini": new Placeable({
        mini: true
    }),
    "chipmunk_mini": new Placeable({
        mini: true
    }),
    "dog_mini": new Placeable({
        mini: true,
        rotation: 2,
        buttonAnchor: {
            x: 0,
            y: 1,
            z: 1.5
        },
        rotationVariants: true
    }),
    "elephant_mini": new Placeable({
        mini: true,
        buttonAnchor: {
            x: 1,
            y: 1,
            z: 1.5
        }
    }),
    "giraffe_mini": new Placeable({
        mini: true
    }),
    "hamster_mini": new Placeable({
        mini: true,
        buttonAnchor: {
            x: 0.5,
            y: 1,
            z: 1.5
        }
    }),
    "hedgehog_mini": new Placeable({
        mini: true,
        buttonAnchor: {
            x: 1,
            y: 1,
            z: 2.5
        }
    }),
    "hippo_mini": new Placeable({
        mini: true
    }),
    "kangaroo_mini": new Placeable({
        mini: true
    }),
    "koala_mini": new Placeable({
        mini: true
    }),
    "lion_mini": new Placeable({
        mini: true
    }),
    "meerkat_mini": new Placeable({
        mini: true,
        rotationVariants: true,
        buttonAnchor: {
            x: 0.5,
            y: 1,
            z: 1.5
        }
    }),
    "monkey_mini": new Placeable({
        mini: true,
        buttonAnchor: {
            x: 1,
            y: 1,
            z: 1.5
        }
    }),
    "owl_mini": new Placeable({
        mini: true
    }),
    "penguin_mini": new Placeable({
        mini: true,
        buttonAnchor: {
            x: 0.5,
            y: 1,
            z: 1.5
        }
    }),
    "platypus_mini": new Placeable({
        mini: true,
        buttonAnchor: {
            x: 1,
            y: 1,
            z: 1.5
        }
    }),
    "red_panda_mini": new Placeable({
        mini: true,
        buttonAnchor: {
            x: 0.5,
            y: 1,
            z: 1.5
        }
    }),
    "snow_leopard_mini": new Placeable({
        mini: true
    }),
    "tiger_mini": new Placeable({
        mini: true,
        buttonAnchor: {
            x: 1,
            y: 1,
            z: 2.5
        }
    }),
    "unicorn_mini": new Placeable({
        mini: true,
        buttonAnchor: {
            x: 0,
            y: 1,
            z: 1.5
        }
    }),
    "zebra_mini": new Placeable({
        mini: true,
        buttonAnchor: {
            x: 1,
            y: 1,
            z: 1.5
        }
    })
};
var ignoreBlocks = [
    "minecraft:air",
    "minecraft:snow_layer",
    "minecraft:short_grass",
    "minecraft:tall_grass",
    "minecraft:orange_tulip",
    "minecraft:pink_tulip",
    "minecraft:red_tulip",
    "minecraft:white_tulip",
    "minecraft:oxeye_daisy",
    "minecraft:allium",
    "minecraft:azure_bluet",
    "minecraft:dandelion",
    "minecraft:poppy",
    "minecraft:blue_orchid",
    "minecraft:cornflower",
    "minecraft:lily_of_the_valley",
    "minecraft:lilac",
    "minecraft:rose_bush",
    "minecraft:peony",
    "minecraft:pink_petals",
    "minecraft:vine",
    "minecraft:oak_leaves",
    "minecraft:birch_leaves",
    "minecraft:deadbush",
    "minecraft:cactus",
    "minecraft:brown_mushroom_block",
    "minecraft:red_mushroom_block",
    "minecraft:red_mushroom",
    "mushroom_stem",
    "minecraft:brown_mushroom",
    "minecraft:bamboo",
    "minecraft:water",
    "minecraft:seagrass",
    "minecraft:kelp",
    "minecraft:brain_coral_fan",
    "minecraft:bubble_coral_fan",
    "minecraft:fire_coral_fan",
    "minecraft:horn_coral_fan",
    "minecraft:tube_coral_fan",
    "minecraft:bubble_column"
];
system.afterEvents.scriptEventReceive.subscribe((event)=>{
    switch(event.id){
        case "wonder_pets:anim_seat_riders":
            //tell all riders of this entity to turn on their sit animation
            var rideable = event.sourceEntity.getComponent(EntityComponentTypes.Rideable);
            //see if any of the riders are wonder pets
            rideable.getRiders().forEach((rider)=>{
                if (rider.typeId.includes("wonder_pets:")) {
                    rider.triggerEvent("wonder_pets:anim_sit");
                }
            });
            break;
        case "wonder_pets:anim_sleep_riders":
            //tell all riders of this entity to turn on their sit animation
            var rideable = event.sourceEntity.getComponent(EntityComponentTypes.Rideable);
            //see if any of the riders are wonder pets
            rideable.getRiders().forEach((rider)=>{
                if (rider.typeId.includes("wonder_pets:")) {
                    rider.triggerEvent("wonder_pets:anim_sleep");
                }
            });
            break;
        case "wonder_pets:place_structure":
            var tags = event.sourceEntity.getTags();
            var dimension = event.sourceEntity.dimension.id;
            for (var tag of tags){
                if (tag.includes("wonder_pets:confirm_")) {
                    world.getDimension(dimension).playSound("wonder_pets:ghost_button_accept", event.sourceEntity.location, {
                        volume: 0.5
                    });
                    var id = tag.replace("wonder_pets:confirm_", "");
                    var ghosts = world.getDimension(dimension).getEntities({
                        type: "wonder_pets:ghost_house",
                        tags: [
                            "wonder_pets_" + id + "_ghost"
                        ]
                    });
                    if (ghosts.length > 0) {
                        var ghost = ghosts[0];
                        //get the structure ID
                        var structureId = Number(ghost.getProperty("wonder_pets:structure_id"));
                        if (!isNaN(structureId) && structureId < Object.keys(placeables).length) {
                            //found a valid structure reference to place
                            var structureName = Object.keys(placeables)[structureId];
                            var rotationSuffix = "";
                            var structureLoc = ghost.location;
                            var rotation;
                            switch(ghost.getProperty("wonder_pets:rotation")){
                                case 0:
                                    if (placeables[structureName].rotationVariants) {
                                        rotationSuffix = "180";
                                    } else {
                                        rotation = StructureRotation.Rotate180;
                                    }
                                    if (placeables[structureName].evenOffsetCorrect) {
                                        structureLoc.x++;
                                        structureLoc.z += 2;
                                    }
                                    break;
                                case 1:
                                    if (placeables[structureName].rotationVariants) {
                                        rotationSuffix = "270";
                                    } else {
                                        rotation = StructureRotation.Rotate270;
                                    }
                                    if (placeables[structureName].evenOffsetCorrect) structureLoc.z += 2;
                                    break;
                                case 2:
                                    rotation = StructureRotation.None;
                                    if (placeables[structureName].evenOffsetCorrect) structureLoc.z++;
                                    break;
                                case 3:
                                    if (placeables[structureName].rotationVariants) {
                                        rotationSuffix = "90";
                                    } else {
                                        rotation = StructureRotation.Rotate90;
                                    }
                                    if (placeables[structureName].evenOffsetCorrect) {
                                        structureLoc.x++;
                                        structureLoc.z++;
                                    }
                            }
                            if (placeables[structureName].structureOffset != undefined) structureLoc = sumVector3(structureLoc, placeables[structureName].structureOffset);
                            try {
                                world.structureManager.place("wonder_pets:" + structureName + rotationSuffix, ghost.dimension, structureLoc, {
                                    rotation: rotation
                                });
                                world.getDimension(dimension).runCommand("event entity @e[type=wonder_pets:ghost_house,tag=wonder_pets_" + id + "_ghost] wonder_pets:despawn");
                                world.getDimension(dimension).playSound("wonder_pets:ghost_house_build", event.sourceEntity.location);
                                if (structureName.includes("_mini")) {
                                    world.getDimension(dimension).spawnParticle("wonder_pets:sparkles_structure_small", ghost.location);
                                } else {
                                    world.getDimension(dimension).spawnParticle("wonder_pets:sparkles_structure", ghost.location);
                                }
                            } catch (e) {
                                world.getDimension(dimension).playSound("wonder_pets:ghost_house_build_failed", event.sourceEntity.location, {
                                    volume: 0.8
                                });
                                event.sourceEntity.runCommand('tellraw @a[r=20] {"rawtext":[{"translate": "hint.structure.cant_place"}]}');
                                world.getDimension(dimension).runCommand("event entity @e[type=wonder_pets:ghost_house,tag=wonder_pets_" + id + "_ghost] wonder_pets:animate_despawn");
                            }
                            world.getDimension(dimension).runCommand("event entity @e[type=wonder_pets:ghost_house_button,tag=" + tag + "] wonder_pets:animate_despawn");
                            if (playerData[id] != undefined) playerData[id].mode = "aim";
                        } else {
                            world.getDimension(dimension).runCommand("event entity @e[type=wonder_pets:ghost_house,tag=wonder_pets_" + id + "_ghost] wonder_pets:animate_despawn");
                        }
                    }
                    break;
                }
            }
            break;
        case "wonder_pets:cancel_structure":
            var tags = event.sourceEntity.getTags();
            for (var tag of tags){
                if (tag.includes("wonder_pets:confirm_")) {
                    var id = tag.replace("wonder_pets:confirm_", "");
                    var returnItemId = "wonder_pets:blueprint";
                    "wonder_pets:item_";
                    for (var idtag of event.sourceEntity.getTags()){
                        if (idtag.includes("wonder_pets:item_")) {
                            returnItemId = idtag.replace("wonder_pets:item_", "");
                        }
                    }
                    var playerSettings = playerData[id];
                    world.getDimension(event.sourceEntity.dimension.id).runCommand("event entity @e[type=wonder_pets:ghost_house_button,tag=" + tag + "] wonder_pets:animate_despawn");
                    if (playerSettings != undefined) {
                        //cancel place mode and remove buttons
                        playerData[id].mode = "aim";
                        playerData[id].heldItem = "";
                        playerData[id].structure = "";
                    }
                    //give back the item to the owner, failing that, to the closest player.
                    var players = world.getAllPlayers();
                    var owner;
                    for (var player of players){
                        if (player.id == id) {
                            owner = player;
                            break;
                        }
                    }
                    if (owner == undefined) {
                        //placer has logged out or is unreachable. Return the item to the closest player instead
                        var owner = world.getDimension(event.sourceEntity.dimension.id).getPlayers({
                            closest: 1,
                            location: event.sourceEntity.location
                        })[0];
                    }
                    if (owner != undefined) {
                        var inventory = owner.getComponent("minecraft:inventory");
                        var placer = new ItemStack(returnItemId, 1);
                        inventory.container.addItem(placer);
                    }
                    world.getDimension(event.sourceEntity.dimension.id).playSound("wonder_pets:ghost_button_decline", event.sourceEntity.location, {
                        volume: 0.5
                    });
                    world.getDimension(event.sourceEntity.dimension.id).runCommand("event entity @e[type=wonder_pets:ghost_house,tag=wonder_pets_" + id + "_ghost] wonder_pets:animate_despawn");
                    break;
                }
            }
            break;
        case "wonder_pets:clearPlayerData":
            playerData = {};
    }
});
system.runInterval(()=>{
    world.getAllPlayers().forEach((player)=>{
        //look for new riders
        var rideable = player.getComponent(EntityComponentTypes.Rideable);
        //see if any of the riders are wonder pets
        var riderList = playerData[player.id]?.riders;
        if (riderList == undefined) {
            riderList = [];
            if (playerData[player.id] != undefined) playerData[player.id].riders = [];
        }
        rideable.getRiders().forEach((rider)=>{
            if (!riderList.includes(rider.id)) {
                playerData[player.id].riders.push(rider.id);
                player.runCommand('/tellraw @s {"rawtext":[{"translate":"hint.wonder_pets.mount.' + rider.typeId.replace("wonder_pets:", "") + '"}]}');
                player.playSound("wonder_pets:pet_mount_player");
            }
        });
        //handle ghost placing
        if (!playerData[player.id]) playerData[player.id] = {
            mode: "aim",
            heldItem: "",
            structure: ""
        };
        var data = playerData[player.id];
        var inventory = player.getComponent("inventory");
        var heldItemId = inventory.container.getItem(player.selectedSlotIndex)?.typeId;
        if (heldItemId && heldItemId.includes("wonder_pets:") && heldItemId.includes("_placer")) {
            data.structure = heldItemId.replace("wonder_pets:", "").replace("_placer", "");
        } else {
            heldItemId = "";
            data.structure = "";
        }
        if (data.mode == "aim") {
            if (heldItemId != data.heldItem) {
                //no longer holding the item. Remove the ghost
                world.getDimension(player.dimension.id).getEntities({
                    tags: [
                        "wonder_pets_" + player.id + "_ghost"
                    ]
                }).forEach((entity)=>{
                    entity.remove();
                });
                data.heldItem = "";
            }
            if (data.heldItem != heldItemId && heldItemId != undefined) {
                data.heldItem = heldItemId;
                if (heldItemId && heldItemId.includes("_placer") && heldItemId.includes("wonder_pets:")) {
                    if (placeables[data.structure]) {
                        //newly held item
                        //despawn any old placers
                        world.getDimension(player.dimension.id).getEntities({
                            tags: [
                                "wonder_pets_" + player.id + "_ghost"
                            ]
                        }).forEach((entity)=>{
                            entity.remove();
                        });
                        //spawn new house
                        spawnGhostHouse(player);
                        data.mode = "aim";
                    }
                }
            }
            if (data.structure != "") {
                var rotation = playerRoundedLocation(player);
                var lookAtBlock = player.getBlockFromViewDirection({
                    maxDistance: 48
                });
                if (lookAtBlock) {
                    var goalBlock = lookAtBlock.block;
                    if (lookAtBlock.face != "Up" && lookAtBlock.face != "Down") {
                        goalBlock = goalBlock[lookAtBlock.face.toLowerCase()]();
                        if (goalBlock) {
                            //go down
                            if (ignoreBlocks.includes(goalBlock.typeId)) {
                                while(ignoreBlocks.includes(goalBlock.typeId) && goalBlock.location.y > world.getDimension(goalBlock.dimension.id).heightRange.min){
                                    goalBlock = goalBlock.below();
                                }
                            }
                        }
                    }
                    if (goalBlock) {
                        var ghostHouses = 0;
                        world.getDimension(player.dimension.id).getEntities({
                            tags: [
                                "wonder_pets_" + player.id + "_ghost"
                            ]
                        }).forEach((entity, index)=>{
                            ghostHouses++;
                            entity.teleport(sumVector3(goalBlock, placeables[data.structure].offset));
                            //entity.setRotation({ x: 0, y: (rotation + placeables[placeableName].rotation) * 90 })
                            entity.setProperty("wonder_pets:rotation", (rotation + placeables[data.structure].rotation) % 4);
                        });
                        if (ghostHouses == 0) {
                            //summon a new ghost house
                            spawnGhostHouse(player, goalBlock);
                        }
                    }
                }
                if (!goalBlock || !lookAtBlock) {
                    world.getDimension(player.dimension.id).getEntities({
                        tags: [
                            "wonder_pets_" + player.id + "_ghost"
                        ]
                    }).forEach((entity)=>{
                        entity.remove();
                    });
                }
            }
        }
    });
}, 2);
function spawnGhostHouse(player, location) {
    var spawnLoc = location ? location : player.location;
    var heightRange = world.getDimension(player.dimension.id).heightRange;
    if (spawnLoc.y > heightRange.max) spawnLoc.y = heightRange.max;
    if (spawnLoc.y < heightRange.min) spawnLoc.y = heightRange.min;
    var houseGhost = world.getDimension(player.dimension.id).spawnEntity("wonder_pets:ghost_house", spawnLoc);
    houseGhost.addTag("wonder_pets_" + player.id + "_ghost");
    houseGhost.triggerEvent("wonder_pets:" + playerData[player.id].structure);
    return houseGhost;
}
function usedPlaceableItem(player, item) {
    if (player == undefined || item == undefined) return;
    var data = playerData[player.id];
    if (data.mode == "aim") {
        var houseGhost = world.getDimension(player.dimension.id).getEntities({
            tags: [
                "wonder_pets_" + player.id + "_ghost"
            ]
        });
        if (houseGhost.length > 0) {
            data.mode = "confirm";
            var rotation = playerRoundedLocation(player);
            houseGhost.forEach((entity)=>{
                var anchorLocation = sumVector3(entity.location, getRotatedOffset(rotation, placeables[data.structure].buttonAnchor));
                if (anchorLocation.y < world.getDimension(player.dimension.id).heightRange.max && entity.location.y > world.getDimension(player.dimension.id).heightRange.min) {
                    //move the anchorLocation up if there's no space
                    var anchorBlock = world.getDimension(player.dimension.id).getBlock(anchorLocation);
                    var validAnchor = true;
                    if (anchorBlock && anchorBlock.typeId != "minecraft:air") {
                        validAnchor = false;
                        var upStep = 0;
                        while(upStep < 8 && anchorBlock != undefined && anchorBlock.typeId != "minecraft:air"){
                            anchorBlock = anchorBlock.above();
                            upStep++;
                        }
                        if (upStep > 7 || anchorBlock == undefined) {
                            player.runCommand('tellraw @s {"rawtext":[{"translate": "hint.structure.buttons_blocked"}]}');
                            player.playSound("wonder_pets:ghost_house_build_failed", {
                                volume: 0.5
                            });
                            data.mode = "aim";
                            world.getDimension(player.dimension.id).getEntities({
                                tags: [
                                    "wonder_pets:confirm_" + player.id
                                ]
                            }).forEach((entity)=>{
                                entity.remove();
                            });
                        } else {
                            anchorLocation = anchorBlock.location;
                            validAnchor = true;
                        }
                    }
                    if (validAnchor) {
                        //delete any stray buttons
                        world.getDimension(player.dimension.id).getEntities({
                            tags: [
                                "wonder_pets:confirm_" + player.id
                            ]
                        }).forEach((entity)=>{
                            entity.remove();
                        });
                        //add house buttons
                        player.playSound("wonder_pets:ghost_house_appear", {
                            volume: 0.5
                        });
                        var confirmButton = world.getDimension(player.dimension.id).spawnEntity("wonder_pets:ghost_house_button", sumVector3(anchorLocation, getRotatedOffset(rotation, {
                            x: -0.5,
                            y: 0,
                            z: 0
                        })));
                        confirmButton.addTag("wonder_pets:confirm_" + player.id);
                        confirmButton.setProperty("wonder_pets:rotation", (rotation + 3) % 4);
                        var cancelButton = world.getDimension(player.dimension.id).spawnEntity("wonder_pets:ghost_house_button", sumVector3(anchorLocation, getRotatedOffset(rotation, {
                            x: 0.5,
                            y: 0,
                            z: 0
                        })));
                        cancelButton.addTag("wonder_pets:confirm_" + player.id);
                        cancelButton.addTag("wonder_pets:item_" + item.typeId);
                        cancelButton.setProperty("wonder_pets:rotation", (rotation + 3) % 4);
                        cancelButton.setProperty("wonder_pets:cancel_button", true);
                        //remove item
                        if (player.getGameMode() != "creative") takeItem(player, item.typeId, 1, true);
                    }
                } else {
                    player.runCommand('tellraw @s {"rawtext":[{"translate": "hint.structure.out_of_bounds"}]}');
                    data.mode = "aim";
                }
            });
        }
    } else {
        data.mode = "aim";
        world.getDimension(player.dimension.id).getEntities({
            tags: [
                "wonder_pets:confirm_" + player.id
            ]
        }).forEach((entity)=>{
            entity.remove();
        });
    }
}
function playerRoundedLocation(player) {
    return (Math.round(player.getRotation().y / 90) + 2) % 4;
}
function getRotatedOffset(rotation, offset) {
    switch(rotation){
        case 0:
            return {
                x: offset.x,
                y: offset.y,
                z: offset.z
            };
        case 1:
            return {
                x: 0 - offset.z,
                y: offset.y,
                z: offset.x
            };
        case 2:
            return {
                x: 0 - offset.x,
                y: offset.y,
                z: 0 - offset.z
            };
        case 3:
            return {
                x: offset.z,
                y: offset.y,
                z: 0 - offset.x
            };
    }
}
function sumVector3(a, b) {
    return {
        x: a.x + b.x,
        y: a.y + b.y,
        z: a.z + b.z
    };
}
function takeItem(player, item, count, prioritizeHand, replaceWith, replaceCount) {
    var inventory = player.getComponent("minecraft:inventory");
    var containerSize = inventory.container.size;
    var newItem;
    if (replaceWith != undefined) {
        newItem = new ItemStack(replaceWith, replaceCount);
    }
    var foundInHand = false;
    if (prioritizeHand && player.selectedSlotIndex != undefined) {
        var it = inventory.container.getItem(player.selectedSlotIndex);
        if (it != undefined && it.typeId == item) {
            if (replaceWith == undefined) {
                if (it.amount > 1) {
                    newItem = new ItemStack(it.typeId, it.amount - 1);
                } else {
                    newItem = undefined;
                }
            }
            inventory.container.getSlot(player.selectedSlotIndex).setItem(newItem);
            foundInHand = true;
        }
    }
    if (!foundInHand) {
        for(var i = 0; i < containerSize; i++){
            var it = inventory.container.getItem(i);
            if (it != undefined && it.typeId == item) {
                if (replaceWith == undefined) {
                    if (it.amount > 1) {
                        newItem = new ItemStack(it.typeId, it.amount - 1);
                    } else {
                        newItem = undefined;
                    }
                }
                inventory.container.getSlot(i).setItem(newItem);
                break;
            }
        }
    }
}
