import { world, EntityComponentTypes, } from "@minecraft/server";
import { allMountIDs, MinecraftEffectTypes } from "../DATA/Config";
export const maxDiveConstant = 85; // max dive angle + 30
export const accelerationConstant = 0.0021739;
export const maxSpeedConstant = 0.0094117647;
export let mountsFlying = {};
export let mountsWereMoving = {};
export let mountsFlyingStopped = {};
export let mountsWereOnGround = {};
export let mountsSpeed = {};
export let oldPlayersXAngle = {};
export let mountsFlyingForwardDebounce = {};
export let playerWasJumping = {};
export const flyingPropId = "kicu_mmad:flying";
export function setFlyProperty(mount, val) {
    try {
        mount.setProperty(flyingPropId, val);
        mount.setProperty(flyingPropId, val);
    }
    catch { }
}
export default function mountFlying(log) {
    let players = world.getAllPlayers();
    for (let pi = 0; pi < players.length; pi++) {
        let player = players[pi];
        const ridingComponent = player.getComponent(EntityComponentTypes.Riding);
        // if (ridingComponent === undefined || !ridingComponent.entity.isValid()) return;
        let mount = undefined;
        try {
            mount = ridingComponent?.entityRidingOn;
        }
        catch (e) { }
        if (mount && mount.isValid()) {
            if (!allMountIDs.includes(mount.typeId))
                return;
            let mountVelocity = mount.getVelocity();
            let mountId = mount.id;
            const playerXAngle = player.getRotation().x;
            let mountNewFlying = mountsFlying[mountId];
            if (mountNewFlying === undefined)
                mountNewFlying = 0;
            let mountOldFlying = mountNewFlying;
            const playerIsJumping = player.isJumping;
            if (playerIsJumping && playerWasJumping[player.id] === false) {
                if (mountOldFlying === 0) {
                    mountNewFlying = -1;
                    if (playerXAngle < -30) {
                        setFlyProperty(mount, 2);
                    }
                    if (playerXAngle >= -30 && playerXAngle < 10) {
                        setFlyProperty(mount, 1);
                    }
                    if (playerXAngle >= 10) {
                        setFlyProperty(mount, 4);
                    }
                }
                else {
                    mountNewFlying = 0;
                }
            }
            playerWasJumping[player.id] = player.isJumping;
            if (!(mountNewFlying === 0) && !mount.isOnGround) {
                const playerViewDirection = player.getViewDirection();
                const mountLocation = mount.location;
                if (Math.round(mountVelocity.x * 1000) / 1000 === 0 && Math.round(mountVelocity.z * 1000) / 1000 === 0) {
                    //log("not moving");
                    if (!mount.isOnGround) {
                        //log("not on ground");
                        mount.addEffect(MinecraftEffectTypes.Invisibility, 5, { showParticles: false });
                        if (mountsWereMoving[mountId] !== true) {
                            mount.clearVelocity();
                            mountsSpeed[mountId] = 0;
                            if (mountsFlying[mountId] != 1) {
                                setFlyProperty(mount, 1);
                                mountsFlying[mountId] = 1;
                                mountsFlyingStopped[mountId] = true;
                                mountsFlyingForwardDebounce[mountId] = 0;
                            }
                        }
                        mountsWereMoving[mountId] = false;
                    }
                    else {
                        setFlyProperty(mount, 0);
                    }
                }
                else if (mountLocation.y < 255 || (mountLocation.y < 318 && mount.dimension.id === "minecraft:overworld")) {
                    const velocityMultiplier = 1 / Math.sqrt(mountVelocity.x * mountVelocity.x + mountVelocity.z * mountVelocity.z);
                    const normalisedHorizontalVelocity = {
                        x: mountVelocity.x * velocityMultiplier,
                        y: mountVelocity.z * velocityMultiplier,
                    };
                    const lookVectorMultiplier = 1 /
                        Math.sqrt(playerViewDirection.x * playerViewDirection.x + playerViewDirection.z * playerViewDirection.z);
                    const normalisedHorizontalViewDirection = {
                        x: playerViewDirection.x * lookVectorMultiplier,
                        y: playerViewDirection.z * lookVectorMultiplier,
                    };
                    const mountFlyingForward = normalisedHorizontalVelocity.x > normalisedHorizontalViewDirection.x - 0.4 &&
                        normalisedHorizontalVelocity.x < normalisedHorizontalViewDirection.x + 0.4 &&
                        normalisedHorizontalVelocity.y > normalisedHorizontalViewDirection.y - 0.4 &&
                        normalisedHorizontalVelocity.y < normalisedHorizontalViewDirection.y + 0.4;
                    if (mountFlyingForward || mountsFlyingForwardDebounce[mountId] > 0) {
                        if (mountFlyingForward) {
                            mountsFlyingForwardDebounce[mountId] = 25;
                        }
                        else {
                            mountsFlyingForwardDebounce[mountId] = mountsFlyingForwardDebounce[mountId] - 1;
                        }
                        const angleConstant = Math.min(Math.max(0, playerXAngle + 40), maxDiveConstant);
                        let mountSpeed = mountsSpeed[mountId];
                        if (mountSpeed == undefined) {
                            mountSpeed = 0;
                        }
                        let maxDiveBoost;
                        if (angleConstant === maxDiveConstant) {
                            maxDiveBoost = 30;
                        }
                        else {
                            maxDiveBoost = 0;
                        }
                        const maxspeed = (angleConstant * maxSpeedConstant + maxDiveBoost * 0.02333333333 + 0.4) * 1.5;
                        let acceleration = (angleConstant * accelerationConstant + maxDiveBoost * accelerationConstant + 0.1) / 5.16;
                        if (mountSpeed > maxspeed) {
                            acceleration = (-acceleration - 0.067829) / 15.125;
                        }
                        let newSpeed;
                        if ((mountSpeed - maxspeed < 0 && acceleration > 0) || (mountSpeed - maxspeed < 0 && acceleration < 0)) {
                            if (Math.abs(mountSpeed - maxspeed) < acceleration) {
                                newSpeed = maxspeed;
                            }
                            else {
                                newSpeed = mountSpeed + acceleration;
                            }
                        }
                        else {
                            newSpeed = mountSpeed + acceleration;
                        }
                        newSpeed = newSpeed < 0.75 ? 0.75 : newSpeed;
                        const oldPlayerXAngle = oldPlayersXAngle[player.id];
                        if (playerXAngle < -30 && (oldPlayerXAngle === undefined || oldPlayerXAngle >= -30)) {
                            setFlyProperty(mount, 2);
                        }
                        if (playerXAngle > -30 && (oldPlayerXAngle === undefined || oldPlayerXAngle <= -30)) {
                            setFlyProperty(mount, 1);
                        }
                        if (playerXAngle < 10 && (oldPlayerXAngle === undefined || oldPlayerXAngle >= 10)) {
                            setFlyProperty(mount, 1);
                        }
                        if (playerXAngle > 10 && (oldPlayerXAngle === undefined || oldPlayerXAngle <= 10)) {
                            setFlyProperty(mount, 4);
                        }
                        if (mountsFlyingStopped[mountId] === true) {
                            mountsFlyingStopped[mountId] = false;
                            if (playerXAngle < -30) {
                                setFlyProperty(mount, 2);
                            }
                            if (playerXAngle >= -30 && playerXAngle < 10) {
                                setFlyProperty(mount, 1);
                            }
                            if (playerXAngle >= 10) {
                                setFlyProperty(mount, 4);
                            }
                        }
                        oldPlayersXAngle[player.id] = playerXAngle;
                        //log("max speed: " + maxspeed.toString());
                        //log("new speed: " + newSpeed.toString());
                        //log("acceleration: " + acceleration.toString());
                        mountsSpeed[mountId] = newSpeed;
                        let isGoingFast = false;
                        if (newSpeed > 0.8) {
                            newSpeed = newSpeed / 2;
                            isGoingFast = true;
                        }
                        let teleportLocation = {
                            x: mountLocation.x + playerViewDirection.x * newSpeed,
                            y: mountLocation.y + playerViewDirection.y * newSpeed,
                            z: mountLocation.z + playerViewDirection.z * newSpeed,
                        };
                        let checkLocation = {
                            x: mountLocation.x + (playerViewDirection.x * newSpeed * 2) / 3,
                            y: mountLocation.y + (playerViewDirection.y * newSpeed * 2) / 3,
                            z: mountLocation.z + (playerViewDirection.z * newSpeed * 2) / 3,
                        };
                        /*
                        log(
                          Math.sqrt(
                            playerViewDirection.x * newSpeed * (playerViewDirection.x * newSpeed) +
                              playerViewDirection.z * newSpeed * (playerViewDirection.z * newSpeed) +
                              playerViewDirection.y * newSpeed * (playerViewDirection.y * newSpeed)
                          ).toString()
                        );*/
                        const teleportBlock = player.dimension.getBlock(checkLocation);
                        const currentBlock = player.dimension.getBlock({
                            x: mountLocation.x + normalisedHorizontalViewDirection.x * 2,
                            y: mountLocation.y,
                            z: mountLocation.z + normalisedHorizontalViewDirection.x * 2,
                        });
                        if (canTeleportThrough(teleportBlock, currentBlock)) {
                            mountsWereMoving[mount.id] = true;
                            mount.teleport(teleportLocation, { checkForBlocks: true, keepVelocity: false });
                        }
                        else {
                            mountNewFlying = 0;
                            setFlyProperty(mount, 0);
                            mount.teleport({
                                x: mountLocation.x - playerViewDirection.x * 1.5,
                                y: mountLocation.y - playerViewDirection.y * 1.5,
                                z: mountLocation.z - playerViewDirection.z * 1.5,
                            }, { checkForBlocks: false, keepVelocity: false });
                        }
                        if (isGoingFast) {
                            const currentBlock = player.dimension.getBlock(teleportLocation);
                            let newTeleportLocation = {
                                x: teleportLocation.x + playerViewDirection.x * newSpeed,
                                y: teleportLocation.y + playerViewDirection.y * newSpeed,
                                z: teleportLocation.z + playerViewDirection.z * newSpeed,
                            };
                            let newCheckLocation = {
                                x: teleportLocation.x + (playerViewDirection.x * newSpeed * 2) / 3,
                                y: teleportLocation.y + (playerViewDirection.y * newSpeed * 2) / 3,
                                z: teleportLocation.z + (playerViewDirection.z * newSpeed * 2) / 3,
                            };
                            const teleportBlock = player.dimension.getBlock(newCheckLocation);
                            if (canTeleportThrough(teleportBlock, currentBlock)) {
                                mountsWereMoving[mount.id] = true;
                                mount.teleport(newTeleportLocation, { checkForBlocks: false, keepVelocity: false });
                            }
                            else {
                                mountNewFlying = 0;
                                setFlyProperty(mount, 0);
                                mount.teleport({
                                    x: teleportLocation.x - playerViewDirection.x * 1.5,
                                    y: teleportLocation.y - playerViewDirection.y * 1.5,
                                    z: teleportLocation.z - playerViewDirection.z * 1.5,
                                }, { checkForBlocks: false, keepVelocity: false });
                            }
                        }
                        mountsWereOnGround[mountId] = false;
                    }
                    else if (normalisedHorizontalVelocity.x > normalisedHorizontalViewDirection.y - 0.4 &&
                        normalisedHorizontalVelocity.x < normalisedHorizontalViewDirection.y + 0.4 &&
                        normalisedHorizontalVelocity.y > -normalisedHorizontalViewDirection.x - 0.4 &&
                        normalisedHorizontalVelocity.y < -normalisedHorizontalViewDirection.x + 0.4) {
                        if (mountsFlying[mountId] != 1) {
                            setFlyProperty(mount, 1);
                            mountsFlying[mountId] = 1;
                            mountsFlyingStopped[mountId] = true;
                        }
                        let teleportLocation = {
                            x: mountLocation.x + normalisedHorizontalViewDirection.y * 0.6,
                            y: mountLocation.y,
                            z: mountLocation.z - normalisedHorizontalViewDirection.x * 0.6,
                        };
                        const teleportBlock = player.dimension.getBlock(teleportLocation);
                        const currentBlock = player.dimension.getBlock({
                            x: mountLocation.x + normalisedHorizontalViewDirection.y * 1.5,
                            y: mountLocation.y,
                            z: mountLocation.z - normalisedHorizontalViewDirection.x * 1.5,
                        });
                        if (canTeleportThrough(teleportBlock, currentBlock)) {
                            mountsWereMoving[mount.id] = true;
                            mount.teleport(teleportLocation, { checkForBlocks: true, keepVelocity: false });
                        }
                        else {
                            mountNewFlying = 0;
                            setFlyProperty(mount, 0);
                            mount.teleport({
                                x: mountLocation.x - playerViewDirection.x * 1.5,
                                y: mountLocation.y,
                                z: mountLocation.z + playerViewDirection.z * 1.5,
                            }, { checkForBlocks: false, keepVelocity: false });
                        }
                    }
                    else if (normalisedHorizontalVelocity.x > -normalisedHorizontalViewDirection.y - 0.4 &&
                        normalisedHorizontalVelocity.x < -normalisedHorizontalViewDirection.y + 0.4 &&
                        normalisedHorizontalVelocity.y > normalisedHorizontalViewDirection.x - 0.4 &&
                        normalisedHorizontalVelocity.y < normalisedHorizontalViewDirection.x + 0.4) {
                        if (mountsFlying[mountId] != 1) {
                            setFlyProperty(mount, 1);
                            mountsFlying[mountId] = 1;
                            mountsFlyingStopped[mountId] = true;
                        }
                        let teleportLocation = {
                            x: mountLocation.x - normalisedHorizontalViewDirection.y * 0.6,
                            y: mountLocation.y,
                            z: mountLocation.z + normalisedHorizontalViewDirection.x * 0.6,
                        };
                        const teleportBlock = player.dimension.getBlock(teleportLocation);
                        const currentBlock = player.dimension.getBlock({
                            x: mountLocation.x - normalisedHorizontalViewDirection.y * 1.5,
                            y: mountLocation.y,
                            z: mountLocation.z + normalisedHorizontalViewDirection.x * 1.5,
                        });
                        if (canTeleportThrough(teleportBlock, currentBlock)) {
                            mountsWereMoving[mount.id] = true;
                            mount.teleport(teleportLocation, { checkForBlocks: true, keepVelocity: false });
                        }
                        else {
                            mountNewFlying = 0;
                            setFlyProperty(mount, 0);
                            mount.teleport({
                                x: mountLocation.x + playerViewDirection.x * 1.5,
                                y: mountLocation.y,
                                z: mountLocation.z - playerViewDirection.z * 1.5,
                            }, { checkForBlocks: false, keepVelocity: false });
                        }
                    }
                    else if (normalisedHorizontalVelocity.x > -normalisedHorizontalViewDirection.x - 0.4 &&
                        normalisedHorizontalVelocity.x < -normalisedHorizontalViewDirection.x + 0.4 &&
                        normalisedHorizontalVelocity.y > -normalisedHorizontalViewDirection.y - 0.4 &&
                        normalisedHorizontalVelocity.y < -normalisedHorizontalViewDirection.y + 0.4) {
                        if (mountsFlying[mountId] != 1) {
                            setFlyProperty(mount, 1);
                            mountsFlying[mountId] = 1;
                            mountsFlyingStopped[mountId] = true;
                        }
                        let teleportLocation = {
                            x: mountLocation.x - playerViewDirection.x * 0.6,
                            y: mountLocation.y - playerViewDirection.y * 0.6,
                            z: mountLocation.z - playerViewDirection.z * 0.6,
                        };
                        const teleportBlock = player.dimension.getBlock(teleportLocation);
                        const currentBlock = player.dimension.getBlock({
                            x: mountLocation.x - playerViewDirection.x * 1.5,
                            y: mountLocation.y - playerViewDirection.y * 1.5,
                            z: mountLocation.z - playerViewDirection.z * 1.5,
                        });
                        if (canTeleportThrough(teleportBlock, currentBlock)) {
                            mountsWereMoving[mount.id] = true;
                            mount.teleport(teleportLocation, { checkForBlocks: true, keepVelocity: false });
                        }
                        else {
                            mountNewFlying = 0;
                            setFlyProperty(mount, 0);
                            mount.teleport({
                                x: mountLocation.x + playerViewDirection.x * 1.5,
                                y: mountLocation.y + playerViewDirection.y * 1.5,
                                z: mountLocation.z + playerViewDirection.z * 1.5,
                            }, { checkForBlocks: false, keepVelocity: false });
                        }
                    }
                }
            }
            else {
                mountsSpeed[mountId] = 0;
                if (mount.isOnGround) {
                    setFlyProperty(mount, 0);
                }
            }
            mountsFlying[mountId] = mountNewFlying;
        }
        else {
            delete oldPlayersXAngle[player.id];
        }
    }
}
function canTeleportThrough(teleportBlock, currentBlock) {
    const passableBlocks = ["tallgrass", "double_plant", "yellow_flower", "red_flower", "snow_layer"];
    const isPassable = (block) => block?.isAir || block?.isLiquid || passableBlocks.some((id) => block?.permutation.matches(id));
    return isPassable(teleportBlock) && isPassable(currentBlock);
}

//# sourceMappingURL=../../../../../_KiCuMountsBPDebug/kicu/mmad/C/Flying.js.map
