// priority: 1000
/**
 * 简单获取暴击率，暴击伤害
 */
function get_kubejs_criticalStrike(player) {
    let item = player.getMainHandItem()

    if (item.item instanceof $ModularItem) {

        //获取主手暴击率,暴击伤害
        let effectLevel = simpleGetTetraEffectLevel(item, 'kubejs_criticalStrike')
        let efficiency = simpleGetEffectEfficiency(item, 'kubejs_criticalStrike')


        //获取暴击增幅的等级
        let all_kubejs_criticalStrike_level = get_specific_effect(player, 'all_kubejs_criticalStrike').level
        effectLevel += all_kubejs_criticalStrike_level

        //获取暴击增幅的效果率值
        let all_kubejs_criticalStrike_efficiency = get_specific_effect(player, 'all_kubejs_criticalStrike').efficiency
        efficiency += all_kubejs_criticalStrike_efficiency

        return {
            level: effectLevel,
            efficiency: efficiency
        }
    } else return {
        level: 0,
        efficiency: 0
    }

}
function dzzl_has_improvement(majormodule, ItemStack, improvement) {
    if (majormodule instanceof $ItemModuleMajor) {
        if (majormodule.getImprovementLevel(ItemStack, improvement) != -1) {
            return true
        } else return false
    }
    return false
}
function forbid_call_thunder(player) {
    let mainitem = player.getMainHandItem()
    let offitem = player.getOffHandItem()
    let forbid_boolean = false
    if (simpleGetTetraEffectLevel(mainitem, 'north_pole') > 0 ||
        simpleGetTetraEffectLevel(offitem, 'north_pole') > 0
    ) {
        forbid_boolean = true
    }
    if (simpleGetTetraEffectLevel(mainitem, 'south_pole') > 0 ||
        simpleGetTetraEffectLevel(offitem, 'south_pole') > 0
    ) {
        forbid_boolean = true
    }
    return forbid_boolean
}
/**
 * 获取主副手的唤雷等级，效率值
 */
function get_mainhand_call_thunder(player) {
    let mainitem = player.getMainHandItem()

    //获取主副手已有唤雷等级
    let main_thunder_level = simpleGetTetraEffectLevel(mainitem, 'call_thunder') || 0

    //获取主副手已有唤雷效率值
    let main_thunder_efficiency = simpleGetEffectEfficiency(mainitem, 'call_thunder') || 0
    return {
        level: main_thunder_level,
        efficiency: main_thunder_efficiency
    }

}
/**
 * 召唤雷霆
 */
function simple_call_thunder(entity, player, damage_value) {
    let item = player.getMainHandItem()
    if (item.item instanceof $ModularItem) {
        player.server.scheduleInTicks(1, () => {
            //雷火超载过滤
            if (simpleGetTetraEffectLevel(item, 'thunder_fire_overload') > 0) return;
            let spawn_entity = entity.level.createEntity("minecraft:lightning_bolt");
            spawn_entity.setPosition(entity.x, entity.y, entity.z);
            spawn_entity.setVisualOnly(true)
            spawn_entity.spawn();
            simpleAttackEntity(true, player, entity, 'minecraft:lightning_bolt', damage_value);
        })
    }
}
/**
 * 简单获取辐射等级和效率值
 */
function simple_get_radiation(player) {
    let item = player.getMainHandItem()
    if (item.item instanceof $ModularItem) {
        //获取辐射等级
        let total_effect = simpleGetTetraEffectLevel(item, 'radiation')
        let total_efficiency = item.item.getEffectEfficiency(item, 'radiation') || 0

        //狱岩词条影响
        if (simpleGetTetraEffectLevel(item, 'hellstone_ingot') > 0) {
            let hellstone_level = simpleGetTetraEffectLevel(item, 'hellstone_ingot')
            let hellstone_efficiency = simpleGetEffectEfficiency(item, 'hellstone_ingot')

            let fire_damage = player.getAttributeTotalValue('kubejs:fire_damage')

            total_effect += fire_damage * hellstone_level / 100
            total_efficiency += fire_damage * hellstone_efficiency / 100
        }
        //核废料词条影响
        if (get_specific_effect(player, 'nuclear_waste').level > 0) {
            let nuclear_waste_level = get_specific_effect(player, 'nuclear_waste').level
            let nuclear_waste_efficiency = get_specific_effect(player, 'nuclear_waste').efficiency

            //获取玩家占据的应力
            let occupation_stress = get_occupation_stress(player)

            total_effect += occupation_stress * nuclear_waste_level / 100
            total_efficiency += occupation_stress * nuclear_waste_efficiency / 100
        }
        //辐无双至词条
        if (simpleGetTetraEffectLevel(item, 'fissile') > 0) {
            //获取福无双至的等级    
            let fissile_level = simpleGetTetraEffectLevel(item, 'fissile')
            let fissile_efficiency = item.item.getEffectEfficiency(item, 'fissile') || 0

            total_effect = total_effect * (1 + fissile_level / 100)
            total_efficiency = total_efficiency * (1 + fissile_efficiency / 100)

        }
        return {
            level: total_effect,
            efficiency: total_efficiency
        }

    } else return {
        level: 0,
        efficiency: 0
    }
}
function simple_all_increased_damage(player, level) {
    let tetra_wear_increased_damag = player.persistentData.getDouble('tetra_wear_increased_damag') ?? 0
    player.persistentData.putDouble('tetra_wear_increased_damag', tetra_wear_increased_damag + level)
}
function simple_main_increased_damage(player, level) {
    let mainhand_increased_damage = player.persistentData.getDouble('mainhand_increased_damage_multiplication') ?? 0
    player.persistentData.putDouble('mainhand_increased_damage_multiplication', mainhand_increased_damage + level)
}
/**
 * 磁场体系下的唤雷等级，效率值
 * 不和其他体系兼容
 */
function get_call_thunder_level(player, item) {
    let mainitem = player.getMainHandItem()
    let offitem = player.getOffHandItem()


    //获取唤雷等级
    let thunder_level = simpleGetTetraEffectLevel(item, 'call_thunder')
    //获取唤雷效率值
    let thunder_efficiency = simpleGetEffectEfficiency(item, 'call_thunder')


    if (simpleGetTetraEffectLevel(item, 'telecore') > 0) {
        //磁流核影响
        thunder_level += Math.min(simpleGetTetraEffectLevel(mainitem, 'north_pole'), simpleGetTetraEffectLevel(offitem, 'south_pole')) / 10

        //磁流核影响
        thunder_efficiency += Math.min(simpleGetEffectEfficiency(mainitem, 'north_pole'), simpleGetEffectEfficiency(offitem, 'south_pole') * 10)
        return {
            level: thunder_level,
            efficiency: thunder_efficiency
        }
    } else return {
        level: thunder_level,
        efficiency: thunder_efficiency
    }
}
/**
 * 获取玩家当前占据的应力
 */
function get_occupation_stress(player) {
    //获取转速
    let gear_shift = get_gear_shift(player)
    //获取占据的应力
    let occupation_stress = get_specific_effect(player, 'occupation_stress').level
    return occupation_stress * (1 * gear_shift / 100)
}
/**
 * 获取玩家转速
 */
function get_gear_shift(player) {
    let gear_shift_level = get_specific_effect(player, 'gear_shift').level
    if (player.hasEffect('kubejs:overload')) {
        gear_shift_level = gear_shift_level * (1 + get_specific_effect(player, 'overload').level / 100)
    }
    return gear_shift_level
}
// 检测 Schematic 是否包含 moduleKey
function hasModuleKey(schematic) {
    if (schematic instanceof $ConfigSchematic) {
        // 获取 SchematicDefinition
        let definition = schematic.definition

        // 遍历 outcomes 检查 moduleKey
        for (let outcome of definition.outcomes) {
            if (outcome.moduleKey != null) {
                return true
            }
        }
    }
    return false;
}
/**
 * 减少物品耐久度，兼容耐久附魔和不可破坏NBT
 * @param {ItemStack} item 要减少耐久的物品
 * @param {number} amount 要减少的耐久值
 */
function reduce_durability(item, amount) {
    if (!item || amount <= 0) return;

    // 检查不可破坏属性
    if (item.nbt?.Unbreakable) return;

    // 计算耐久减免概率
    let enchant_level = item.getEnchantmentLevel('minecraft:unbreaking') || 0;
    let math = (60 + 40 / (enchant_level + 1)) / 100

    // 随机判断是否减免
    if (Math.random() < math) {
        item.damageValue = item.damageValue + amount
    }
}
/**
 * 检测模块前后变化的工具函数
 * @param {ItemStack} targetStack - 升级前的物品堆栈
 * @param {ItemStack} upgradedStack - 升级后的物品堆栈
 * @returns {Object} - 返回变化前后的模块信息
 */
function detectModuleChanges(targetStack, upgradedStack) {
    // 防御性检查
    if (!targetStack || !upgradedStack) {
        console.error("检测到空物品堆栈");
        return { added: [], removed: [], unchanged: [] };
    }

    let oldModules = targetStack.getItem().getMajorModules(targetStack) || [];
    let newModules = upgradedStack.getItem().getMajorModules(upgradedStack) || [];

    // 过滤掉可能为null的模块
    oldModules = oldModules.filter(module => module && module.key);
    newModules = newModules.filter(module => module && module.key);

    let oldModuleKeys = oldModules.map(module => module.key);
    let newModuleKeys = newModules.map(module => module.key);

    let addedModules = newModuleKeys.filter(key => !oldModuleKeys.includes(key));
    let removedModules = oldModuleKeys.filter(key => !newModuleKeys.includes(key));
    let unchangedModules = oldModuleKeys.filter(key => newModuleKeys.includes(key));

    return {
        added: addedModules,
        removed: removedModules,
        unchanged: unchangedModules
    };
}


/**
 * 检测某物品是否含有某improvement
 */
function has_improvement(item, improvement) {
    let modularItem = item.getItem();
    let boolean = false
    // 获取所有主要模块
    let modules = modularItem.getMajorModules(item);

    for (let module of modules) {
        if (module && module.getImprovement(item, improvement) != null) {
            boolean = true;
            break;
        }
    }
    return boolean
}
/**
 * 移除或降低物品的改进等级
 * @param {ItemStack} item - 要修改的物品
 * @param {string} improvement - 改进的唯一标识符（key）
 * @param {boolean} removeCompletely - 是否完全移除改进（true：完全移除；false：降低一级）
 * @param {Object} module - 更改的module
 */
function remove_improvement(item, improvement, removeCompletely, module) {
    if (module instanceof $ItemModuleMajor) {
        if (module && module.getImprovement(item, improvement) != null) {
            if (removeCompletely) {
                // 完全移除指定的改进
                module.removeImprovement(item, improvement);
            } else {
                // 获取当前改进等级
                let level = module.getImprovementLevel(item, improvement);
                if (level > 1) {
                    // 降低改进等级（当前等级减1）
                    module.addImprovement(item, improvement, level - 1);
                } else {
                    // 如果改进等级为1，则完全移除
                    module.removeImprovement(item, improvement);
                }
            }
        }
    }
}


/**
* 获取玩家所有的tetra饰品
* @param {Internal.Player} player - 玩家实体
* @returns {Array} 返回tetra饰品物品数组
*/
function getTetraCurios(player) {
    let tetraItems = [];

    // 使用API获取玩家的所有饰品
    let api = new $CuriosApi();
    // 获取装备的饰品（返回Optional）
    let optionalCurios = api.getCuriosHelper().getEquippedCurios(player);

    if (!optionalCurios.isPresent()) return;


    let resolved = optionalCurios.resolve();
    if (!resolved.isPresent()) return
    let curios = resolved.get();

    // 遍历所有饰品槽位
    for (let slot = 0; slot < curios.getSlots(); slot++) {
        let item = curios.getStackInSlot(slot);

        // 只添加模块化物品
        if (item.item instanceof $ModularItem) {
            tetraItems.push(item);
        }
    }

    return tetraItems;
}


/**
* 获取某个半径内的生物
* @param {Internal.Level} level
* @param {Vec3} pos
* @param {Number} radius
* @returns {Array<Internal.LivingEntity>}
*/
function getLivingWithinRadius(level, pos, radius) {
    if (!level || !pos || !radius) return [];

    try {
        let area = new AABB.of(
            pos.x() - radius, pos.y() - radius, pos.z() - radius,
            pos.x() + radius, pos.y() + radius, pos.z() + radius
        );
        if (!area) return [];

        let entityAABBList = level.getEntitiesWithin(area);
        if (!entityAABBList) return [];

        let entityList = [];
        entityAABBList.forEach(entity => {
            if (entity && entity.position && entity.isLiving &&
                entity.position().distanceTo(pos) <= radius) {
                entityList.push(entity);
            }
        });
        return entityList;
    } catch (e) {
        console.error("getLivingWithinRadius error:", e);
        return [];
    }
}

//来自屋喵大佬的代码（拼好码）
function getPlayerLightLevel(player) {
    let level = player.level;
    let pos = player.blockPosition();
    let skyLight = level.getRawBrightness(pos, 15);
    let blockLight = level.getRawBrightness(pos, 0);
    let lightLevel;
    if (level.isDay() && !level.isRaining() && !level.isThundering()) {
        lightLevel = level.getRawBrightness(pos, 0);
    } else {
        lightLevel = Math.min(skyLight, blockLight);
    }

    let item = player.getMainHandItem();
    if (simpleGetTetraEffectLevel(item, 'pure_darkness') > 0) {
        lightLevel = lightLevel * (1 - simpleGetTetraEffectLevel(item, 'pure_darkness'))
    }

    return lightLevel;
}

function normalizeVector(vector) {
    const length = Math.sqrt(vector.x() * vector.x() + vector.y() * vector.y() + vector.z() * vector.z());
    if (length === 0) {
        return { x: 0, y: 0, z: 0 };
    }
    return {
        x: vector.x() / length,
        y: vector.y() / length,
        z: vector.z() / length
    };
}


/**
* 获取伤害类型的ResourceKey
* @param {Special.DamageType} damageTypeName 
*/
function damageTypeKey(damageTypeName) { return $ResourceKey.create($Registries.DAMAGE_TYPE, damageTypeName) }
/**
 * 对实体造成伤害
 * @param {boolean} invulnerableTime - 是否忽略无敌时间
 * @param {$LivingEntity_} source - 伤害来源实体
 * @param {$LivingEntity_} target - 目标实体
 * @param {Special.DamageType} damagetype - 伤害类型
 * @param {number} amount - 伤害值
 */
function simpleAttackEntity(invulnerableTime, source, target, damagetype, amount) {
    // 保存目标实体原本的无敌时间，用于后续恢复
    let defTime = target.invulnerableTime
    // 判断是否需要忽略无敌时间
    if (invulnerableTime) {
        // 若目标当前处于无敌状态（无敌时间>0）
        if (target.invulnerableTime) {
            // 临时将目标无敌时间设为0（取消无敌状态）
            target.invulnerableTime = 0
            // 执行攻击逻辑
            attack_entity(target, damagetype, source, amount)
            // 攻击后恢复目标原本的无敌时间
            target.invulnerableTime = defTime
        } else {
            // 目标当前无无敌时间，直接执行攻击
            attack_entity(target, damagetype, source, amount)
        }
    } else {
        // 不需要忽略无敌时间，直接执行攻击
        attack_entity(target, damagetype, source, amount)
    }

    // 具体执行攻击的内部函数
    function attack_entity(target, damagetype, source, amount) {
        // 处理伤害来源实体为null的情况
        if (source == null) {
            // 获取目标当前生命值
            let health = target.getHealth()
            // 若目标生命值大于本次伤害量，执行常规伤害
            if (health > amount) {
                target.attack(target.damageSources().source(damageTypeKey(damagetype), source, source), amount)
            } else {
                // 若目标生命值小于等于本次伤害量，直接将生命值设为1
                target.setHealth(1)
            }
        } {
            // 伤害来源实体不为null时，直接执行常规伤害
            target.attack(target.damageSources().source(damageTypeKey(damagetype), source, source), amount)
        }
    }
}

/**
* @param available_modular 允许进行此操作的物品类型,如果填all表示所有的都行
* @param effect_name       效果的名称
* @param enchantment       附魔名称
* @param item              要操作的物品
*/
function forgeing_enchantment(available_modular, effect_name, enchantment, item) {
    // 检查物品是否为允许的类型，若不是则直接返回
    if (item == available_modular || available_modular == 'all') {
        // 检查物品是否拥有该效果
        if (hasItemEffect(item, effect_name)) {
            // 获取物品当前的效果等级
            let effectValue = simpleGetTetraEffectLevel(item, effect_name);
            // 获取物品当前的附魔等级，若未附魔则返回0
            let enchant_level = item.getEnchantmentLevel(enchantment) || 0;

            // 如果附魔等级已经大于或等于效果等级，则无需调整
            if (enchant_level >= effectValue) return;

            // 如果物品已经有该附魔但等级低于效果等级，则移除原有附魔
            if (enchant_level) {
                // 获取物品的NBT数据
                let nbt = item.getNbt();
                // 获取附魔列表（TagList类型）
                let enchantments = nbt.getList("Enchantments", 10);

                // 过滤掉指定的附魔，保留其他附魔
                let newEnchantments = enchantments.filter(enchant => {
                    return enchant.getString("id") !== enchantment;
                });

                // 更新NBT数据中的附魔列表
                nbt.put("Enchantments", newEnchantments);
                item.setNbt(nbt);
            }

            // 将物品的附魔等级设置为与效果等级一致
            item.enchantStack(enchantment, effectValue);
        }
    }
}

function Armor_Conversion_ratio_increase(player, level) {
    let armor = player.getAttributeTotalValue('minecraft:generic.armor')
    let armor_toughness = player.getAttributeTotalValue('minecraft:generic.armor_toughness')
    let BaseWeight = 0.038 //基础权重
    let growthWeight = 1.53 //成长权重

    //非线性盔甲和韧性权重比转化
    let armorValue = Math.pow(armor, 0.7) * 1.1
    let toughnessValue = Math.pow(armor_toughness, 0.8) * 1.2
    //转化增伤比例
    let ratio = BaseWeight * Math.pow(growthWeight, level) * (armorValue + toughnessValue)
    //确保最低增伤
    return Math.max(1 + ratio, 1)
}

// 获取下一个弹跳目标
function getNextBounceTarget(currentTarget, bounceTargets, player) {
    // 过滤死亡目标
    let aliveBounceTargets = bounceTargets.filter(target => target.isAlive() && target != player);

    if (aliveBounceTargets.length <= 1) {
        // 如果只有当前只有目标或没有目标，就继续弹跳到当前目标
        return currentTarget.isAlive() ? currentTarget : null;
    }

    // 选择除当前目标外的随机目标
    let otherTargets = aliveBounceTargets.filter(target => target != currentTarget);
    if (otherTargets.length > 0) {
        let randomIndex = Math.floor(Math.random() * otherTargets.length);
        return otherTargets[randomIndex];
    }

    // 如果没有其他目标，回到当前目标
    return currentTarget.isAlive() ? currentTarget : null;
}






// 功能就是扫描玩家周围的方块
// 然后为了不那么卡，把扫描任务分散到多帧里去，然后再限制一下每帧扫描的方块数量

// 全局存储扫描任务状态
let BLOCK_SCAN_TASKS = {};

/**
 * 扫描玩家周围的某种方块，并返回数量
 * @param {Player} player - 执行扫描的玩家
 * @param {string[]} targetBlockIds - 要扫描的目标方块ID数组
 * @param {number} radius - 扫描半径（从玩家位置向各方向延伸）
 * @param {Function} onComplete - 扫描完成时的回调函数
 * @param {number} maxPerTick - 每tick最大处理方块数（默认200）
 */
function startBlockScan(player, targetBlockIds, radius, onComplete, maxPerTick) {
    // 设置默认值
    if (maxPerTick == null) maxPerTick = 200;

    // 使用玩家名称作为任务唯一标识符
    let key = player.name;

    // 取消旧任务 - 防止重复扫描
    if (BLOCK_SCAN_TASKS[key]) {
        delete BLOCK_SCAN_TASKS[key];
    }

    // 安全检查：只在服务端执行
    let level = player.level;
    if (level.isClientSide()) return;

    // 获取玩家当前位置作为扫描中心点
    let center = player.block.pos;

    // 将目标方块ID数组转换为对象，用于快速查找
    // 使用对象比数组查找更快
    let targetSet = {};
    for (let i = 0; i < targetBlockIds.length; i++) {
        targetSet[targetBlockIds[i]] = true;
    }

    // 存储任务状态到全局变量
    // 这里保存了扫描的所有必要状态信息
    BLOCK_SCAN_TASKS[key] = {
        player: player,           // 玩家引用
        center: center,          // 扫描中心坐标
        targetSet: targetSet,    // 目标方块快速查找表
        radius: radius,          // 扫描半径
        maxPerTick: maxPerTick,  // 每tick处理的最大方块数（性能控制）
        x: -radius,              // 当前扫描的X坐标偏移（从-radius开始）
        y: -radius,              // 当前扫描的Y坐标偏移
        z: -radius,              // 当前扫描的Z坐标偏移
        count: 0,                // 已找到的目标方块计数
        onComplete: onComplete   // 扫描完成后的回调函数
    };

    // 立即处理第一帧，开始扫描流程
    continueBlockScan(key);
}

/**
 * 继续处理下一帧（由调度器调用）
 * @param {string} taskKey - 任务唯一标识符（玩家名称）
 */
function continueBlockScan(taskKey) {
    // 获取任务状态，如果任务不存在则退出
    let task = BLOCK_SCAN_TASKS[taskKey];
    if (!task) return;

    // 解构任务状态变量，便于使用
    let { player, center, targetSet, radius, maxPerTick } = task;

    // 再次检查是否在服务端（安全冗余）
    let level = player.level;
    if (level.isClientSide()) {
        delete BLOCK_SCAN_TASKS[taskKey];
        return;
    }

    // 当前tick已处理的方块计数器
    let processed = 0;

    // 主扫描循环：在当前tick内处理最多maxPerTick个方块
    while (processed < maxPerTick) {
        // 计算当前要检查的方块世界坐标
        // center.offset(x, y, z) 返回中心点加上偏移量的新坐标
        let pos = center.offset(task.x, task.y, task.z);

        // 获取该位置的方块ID
        let blockId = level.getBlock(pos).id.toString();

        // 检查是否是目标方块
        if (targetSet[blockId]) {
            task.count++;  // 如果是目标方块，增加计数
        }

        // ========== 三维坐标遍历逻辑 ==========
        // 采用从内到外的遍历顺序：Z -> Y -> X

        // 1. 先增加Z坐标
        task.z++;

        // 2. 如果Z坐标超出半径范围，重置Z并增加Y
        if (task.z > radius) {
            task.z = -radius;  // Z坐标回到起点
            task.y++;          // 增加Y坐标

            // 3. 如果Y坐标超出半径范围，重置Y并增加X
            if (task.y > radius) {
                task.y = -radius;  // Y坐标回到起点
                task.x++;          // 增加X坐标

                // 4. 如果X坐标超出半径范围，说明扫描完成
                if (task.x > radius) {
                    // 扫描完成处理
                    let finalCount = task.count;  // 保存最终计数
                    let onComplete = task.onComplete;  // 保存回调函数

                    // 清理任务状态
                    delete BLOCK_SCAN_TASKS[taskKey];

                    // 执行完成回调，传递找到的方块数量
                    onComplete(finalCount);
                    return;  // 退出函数，扫描结束
                }
            }
        }

        // 增加已处理方块计数
        processed++;
    }

    // ========== 关键：分帧调度 ==========
    // 当前tick处理完成，调度在1个tick后继续处理
    // 这避免了单次处理过多方块造成的服务器卡顿
    player.server.scheduleInTicks(1, () => {
        continueBlockScan(taskKey);
    });
}




/**
 * 获取玩家所在位置的生物群系注册名（ResourceLocation 字符串）
 * @param {Internal.Player} player - 玩家
 * @returns {string|null} 生物群系的注册名，如 "minecraft:plains"；失败时返回 null
 */
function getPlayerBiomeKey(player) {
    if (!player || player.level.isClientSide()) {
        return null;
    }

    let level = player.level;
    let pos = player.block.pos; // 使用脚下方块位置

    try {
        let biome = level.getBiome(pos);
        if (!biome) return null;

        let unwrapped = biome.unwrapKey();
        if (!unwrapped.isPresent()) return null;

        let key = unwrapped.get();
        let location = key.location();
        return location.toString();
    } catch (e) {
        console.error("Error getting biome key:", e);
        return null;
    }
}