本篇教程由作者设定未经允许禁止转载。

需要KubeJSLootJS: KubeJS Addon

需要注意的是lootjs的修改通过Just Enough Resources是看不到的,需要用高级战利品信息显示才能看见,两个可以一起装,后者会覆盖前者的页面


本教程只记录了我的整合包里所用到的魂石,没有涉及到的在未来可能会添加(下一步是加植魔,但是要做完相关的其他内容才会来做这个),也可能不会(如机械动力以及枪相关附属等)

我一个人编写一个人测试,难免会有隐藏的bug,如果你有发现任何bug随时向我反馈


别忘了event.remove({ mod: 'mine_fargo' })


先列出目前添加的所有内容

魂石名称获取方法


空白魂石合成
矿物之魂在植物魔法的台子上合成
煤炭魂石挖矿概率获得
铜魂石挖矿概率获得
青金石魂石挖矿概率获得
铁魂石挖矿概率获得
红石魂石挖矿概率获得
金魂石挖矿概率获得
绿宝石魂石挖矿概率获得
钻石魂石挖矿概率获得
下界合金魂石挖矿概率获得


自然之魂
冰雪魂石在冰原或雪原等流浪者会刷新的地方用火焰附加/怒火击杀流浪者有1%的概率掉落
熔岩魂石在细雪里(ticksFrozen>0)击杀烈焰人50%概率获得一个
蘑菇魂石在蘑菇岛使用剪刀5%掉落
下界魂石在下界,每着火5秒1%的概率触发一次掉落
末地魂石吃紫颂果、右键末影珍珠每次分别有1%的概率掉落,上述两种行为每次都会积累得分,得分满100额外给一个
海洋魂石每1000分得一个,分数来源:Score=(游泳距离   ×1.0)+(水面行走×0.5)+(水下行走 ×1.1)+(坐船×0.3)
翠绿魂石收获作物的时候1%概率获得
森林魂石在森林、繁花森林、桦木森林、黑森林、丛林、稀疏丛林、竹林、樱花树林群系,当玩家每隔10秒,有1%在玩家脚下生成一个。累计30分钟额外掉落一个


生灵之魂“掠夺”附魔不会生效
狱灵魂石击杀僵尸猪灵、猪灵、猪灵蛮兵有1%的概率掉落,100次独立保底一次
亡灵魂石击杀亡灵生物1%掉落一个,100个保底,如果武器有亡灵杀手变成5%,此外凋灵固定掉一个
节肢魂石击杀原版蜘蛛和洞穴蜘蛛1%掉落一个,100个保底,如果武器有节肢杀手变成5%
动物魂石击杀动物(同时有age和InLove数据值的生物)时1%掉落
水生魂石击杀亡灵生物1%掉落一个,100个保底,如果武器有水生杀手变成5%
飞翼魂石杀100只幻翼掉一个


灾变之魂
焰魔魂石加入战利品表
利维坦魂石加入战利品表
咒翼灵骸魂石加入战利品表
末影守卫魂石加入战利品表
远古遗魂魂石加入战利品表
先驱者魂石加入战利品表
下界合金巨兽魂石加入战利品表
斯库拉魂石

加入战利品表



巨龙之魂
龙骨魂石所有龙有概率掉落
炎血魂石龙骨魂石在冶炼炉浇筑火龙血
霜血魂石龙骨魂石在冶炼炉浇筑冰龙血
霆血魂石龙骨魂石在冶炼炉浇筑雷龙血
龙炎魂石龙骨魂石在对应锻炉里
龙霜魂石龙骨魂石在对应锻炉里
龙霆魂石龙骨魂石在对应锻炉里


冰火之魂
独眼巨人魂石加入战利品表
蛇发女妖魂石加入战利品表
海蟒魂石加入战利品表
食人妖魂石加入战利品表
海马魂石加入战利品表
死亡蠕虫魂石加入战利品表
塞壬魂石(模组特殊处理)加入战利品表
九头蛇魂石(模组特殊处理)加入战利品表


乐事魂石进食时有概率获得
海王魂石加到海王的战利品表里


超然之魂
锚定魂石任务兑换  
磁铁魂石任务兑换   捡起物品时0.1%概率获得,无保底
危险魂石任务兑换   杀死任意生物有0.1%获得,无保底
替死魂石任务兑换   在灵魂破碎状态且身上有灵魂窃取buff的时候击杀任意生物100%获得
金果魂石任务兑换   每次吃(附魔)金苹果有(15%)5%概率获得,无保底
潮水魂石任务兑换   身上有潮涌buff时,每三分钟获取一个
修复魂石任务兑换


伊始之魂一即全,全即一






kjs代码,都是服务端,可以直接放在一个文件里 ,我这里是图方便全放一起了,你大可不必如此

const CHANCE_SNOW = 0.01
const CHANCE_LAVA = 0.5
const CHANCE_MUSH = 0.01
const CHANCE_LUSH = 0.01
const CHANCE_GREEN = 0.01
const CHANCE_FOREST = 0.001
const CHANCE_NETHER = 0.01
const CHANCE_END = 0.01
const CHANCE_UNDEAD = 0.01
const CHANCE_SMITE = 0.01
const CHANCE_ARTHROPOD = 0.01
const CHANCE_ANIMAL = 0.01
const CHANCE_WATER = 0.01
const CHANCE_DRAGON = 0.1
const CHANCE_MAGNET = 0.001
const CHANCE_DANGER = 0.001
const CHANCE_GOLDEN_APPLE = 0.05


//矿物相关的内容直接使用了战利品表覆写,在data里覆盖了原版内容,在此不显示,可以改用lootjs实现


let MobType = Java.loadClass("net.minecraft.world.entity.MobType")

EntityEvents.death(event => {
    let { entity, player, level, source } = event
    if (source.getActual().type == "minecraft:player")
        player = source.getActual()//为player重新赋值
    else return

    let weapon = player ? player.getMainHandItem() : null

    var coldBiomes = [
        'deep_cold_ocean',
        'deep_frozen_ocean',
        'frozen_peaks',
        'frozen_ocean',
        'frozen_river',
        'grove',
        'ice_spikes',
        'snowy_beach',
        'snowy_plains',
        'snowy_slopes',
        'snowy_taiga']


    //冰雪魂石:在冰原或雪原等流浪者会刷新的地方用火焰附加/怒火击杀流浪者有1%的概率掉落
    if (entity.type == "minecraft:stray")
        //是player发起的攻击
        if (player && weapon) {

            //判定武器是否有对应附魔或者特性
            if ((weapon.hasTag('tconstruct:modifiable') && SimpleTCon.hasModifier(weapon, "tconstruct:fiery") ||
                weapon.getEnchantmentLevel("minecraft:fire_aspect") > 0))
                //判定群系
                if (coldBiomes.some((element) => element == level.getBiome(player.blockPosition()).unwrapKey().get().getPath()))
                    //概率
                    if (Math.random() < CHANCE_SNOW)
                        entity.block.popItem(Item.of("mine_fargo:snow_soul_stone"))


        }


    //熔岩魂石:在细雪里(ticksFrozen>0)击杀烈焰人50%概率获得一个
    if (entity.type == "minecraft:blaze")
        if (player && player.ticksFrozen > 0)
            if (Math.random() < CHANCE_LAVA)
                entity.block.popItem(Item.of("mine_fargo:lava_soul_stone"))

    // player.setStatusMessage(event.entity.mobType == MobType.ILLAGER ? Text.red("ILLAGER") :
    //     event.entity.mobType == MobType.WATER ? Text.yellow("WATER") :
    //         event.entity.mobType == MobType.UNDEFINED ? Text.white("UNDEFINED") :
    //             event.entity.mobType == MobType.UNDEAD ? Text.red("UNDEAD") :
    //                 event.entity.mobType == MobType.ARTHROPOD ? Text.yellow("ARTHROPOD") :
    //                     Text.white("..."))


    //狱灵魂石:击杀僵尸猪灵、猪灵、猪灵蛮兵有1%的概率掉落,100次独立保底一次
    multipleKillCounterList(event, ["minecraft:zombified_piglin", "minecraft:piglin", "minecraft:piglin_brute"],
        CHANCE_NETHER, "nether_count", "mine_fargo:nether_soul_stone", true)

    //亡灵魂石:击杀亡灵生物1%掉落一个,100个保底,如果武器有亡灵杀手变成5%,此外凋灵固定掉一个
    if (entity.mobType && entity.mobType == MobType.UNDEAD) {
        let _CHANCE_SMITE = CHANCE_SMITE
        if ((weapon.hasTag('tconstruct:modifiable') && SimpleTCon.hasModifier(weapon, "tconstruct:smite") ||
            weapon.getEnchantmentLevel("minecraft:smite") > 0))
            _CHANCE_SMITE *= 5

        multipleKillCounterByMobType(event, MobType.UNDEAD, _CHANCE_SMITE, "undead_count", "mine_fargo:death_soul_stone", true)
        if (entity.type == "minecraft:wither")
            entity.block.popItem(Item.of("mine_fargo:death_soul_stone"))
    }

    //节肢魂石:击杀原版蜘蛛和洞穴蜘蛛1%掉落一个,100个保底,如果武器有节肢杀手变成5%
    if (entity.type == 'minecraft:cave_spider' || entity.type == 'minecraft:spider') {
        let _CHANCE_ARTHROPOD = CHANCE_ARTHROPOD
        if ((weapon.hasTag('tconstruct:modifiable') && SimpleTCon.hasModifier(weapon, "tconstruct:bane_of_sssss") ||
            weapon.getEnchantmentLevel("minecraft:bane_of_arthropods") > 0))
            _CHANCE_ARTHROPOD *= 5
        multipleKillCounterByMobType(event, MobType.ARTHROPOD, _CHANCE_ARTHROPOD, "arthropod_count", "mine_fargo:arthropod_soul_stone", true)
    }

    //动物魂石:击杀动物(同时有age和InLove数据值的生物)时1%掉落
    if (entity.nbt.contains('Age') && entity.nbt.contains('InLove'))
        if (player && Math.random() < CHANCE_ANIMAL) {
            entity.block.popItem(Item.of("mine_fargo:animal_soul_stone"))
            player.setStatusMessage(Text.green("动物之魂!"));
        }

    //水生魂石:击杀水生生物(原版水生生物,如果模组继承了对应值应该也算)1%掉落一个,100个保底,如果武器有水生杀手(匠魂的特性,原版没有对应附魔)变成5%
    if (entity.mobType && entity.mobType == MobType.WATER) {
        let _CHANCE_WATER = CHANCE_WATER
        if ((weapon.hasTag('tconstruct:modifiable') && SimpleTCon.hasModifier(weapon, "tconstruct:antiaquatic")))
            _CHANCE_WATER *= 5

        multipleKillCounterByMobType(event, MobType.WATER, _CHANCE_WATER, "water_count", "mine_fargo:aquatic_soul_stone", true)
    }
    //飞翼魂石:每100只幻翼会掉一个
    multipleKillCounter(event, 'minecraft:phantom', 100, "wings_count", 'mine_fargo:wing_soul_stone', true)

    //龙骨魂石:所有龙死后有10%概率掉落(右键龙骨架不方便)
    multipleKillCounterList(event, ["iceandfire:fire_dragon", "iceandfire:ice_dragon", "iceandfire:lightning_dragon"],
        CHANCE_DRAGON, "dragon_count", "mine_fargo:dragon_bone_soul_stone", true)

})
//蘑菇魂石:在蘑菇岛使用剪刀5%掉落
ItemEvents.entityInteracted(event => {
    let { item, player, level, target } = event
    if (level.getBiome(player.blockPosition()).unwrapKey().get().getPath() == "mushroom_fields")
        if (item.hasTag("forge:shears"))
            if (Math.random() < CHANCE_MUSH)
                target.block.popItem(Item.of("mine_fargo:mushroom_soul_stone"))
})
//乐事魂石:进食时有概率获得
ItemEvents.foodEaten(event => {
    let { player } = event
    if (Math.random() < CHANCE_LUSH) {
        player.block.popItem(Item.of("mine_fargo:farmers_delight_soul_stone"))
        player.setStatusMessage(Text.yellow("获得乐事魂石!"));
    }
})

//末地魂石:吃紫颂果、右键末影珍珠每次分别有1%的概率掉落,上述两种行为每次都会积累得分,得分满100额外给一个
ItemEvents.foodEaten(event => {
    let { item, player } = event
    if (item.getId() == 'minecraft:chorus_fruit') {
        if (Math.random() < CHANCE_END)
            player.block.popItem(Item.of("mine_fargo:ender_soul_stone"))

        //此处处理规避data中无内容的情况
        let count = player.data.get("end_count")
        if (isNaN(count)) count = 0;
        count++;

        if (count >= 100) {
            player.block.popItem(Item.of("mine_fargo:ender_soul_stone"))
            player.setStatusMessage(Text.white("额外的馈赠!"));
            player.data.put("end_count", count -= 100)
        }
        player.data.put("end_count", count);
    }
})
ItemEvents.rightClicked(event => {
    let { item, player } = event
    if (item.getId() == 'minecraft:ender_pearl') {
        if (Math.random() < CHANCE_END)
            player.block.popItem(Item.of("mine_fargo:ender_soul_stone"))

        let count = player.data.get("end_count")
        if (isNaN(count)) count = 0;
        count++;

        if (count >= 100) {
            player.block.popItem(Item.of("mine_fargo:ender_soul_stone"))
            player.setStatusMessage(Text.white("额外的馈赠!"));
            player.data.put("end_count", count -= 100)
        }
        player.data.put("end_count", count);
    }
})
//用于每分钟触发一次
let oceanTimer = 0

PlayerEvents.tick(event => {
    let { player, server, level } = event
    //下界魂石:在下界,每着火5秒触发一次掉落,1%的概率
    if (player.level.dimension == "minecraft:the_nether") {
        if (player.isOnFire()) {
            let cooldownTicks = 100;

            if (!player.data.get("nether_timer")) player.data.put("nether_timer", 0)
            let nether_timer = player.data.get("nether_timer")
            if (level.getTime() - nether_timer >= cooldownTicks) {
                player.data.put("nether_timer", level.getTime())
                if (Math.random() < CHANCE_NETHER)//已经将该物品设置为防火
                {
                    player.block.popItem(Item.of("mine_fargo:nether_soul_stone"))
                    player.setStatusMessage(Text.gold("真金不怕火炼!"));
                }

            }
        }

    }


    //简单的延时,每分钟触发一次
    if (level.getTime() - oceanTimer >= 1200) {
        oceanTimer = level.getTime()
        //海洋魂石:每1000分得一个,分数来源:Score=(游泳距离 ×1.0)+(水面行走×0.5)+(水下行走 ×1.1)+(坐船×0.3)
        let overworld = server.getLevel('minecraft:overworld')
        //这里用了 FilesJS来读取存档里的数据文件,如果你的电脑由于任何原因不让访问这里就全失效
        let uuid = player.getUuid()
        let saveName = overworld.getServer().storageSource.getDimensionPath(overworld.getDimensionKey()).getFileName().toString();
        let totalStats = FilesJS.readFile(`saves/${saveName}/stats/${uuid}.json`)

        //粗糙的手动处理
        let swiming = parseInt((totalStats.split("\"minecraft:swim_one_cm\":")[1] == undefined ? "0,"
            : totalStats.split("\"minecraft:swim_one_cm\":")[1]).split(",")[0]) / 100
        let walkOnWater = parseInt((totalStats.split("\"minecraft:walk_on_water_one_cm\":")[1] == undefined ? "0,"
            : totalStats.split("\"minecraft:walk_on_water_one_cm\":")[1]).split(",")[0]) / 100
        let walkUnderwater = parseInt((totalStats.split("\"minecraft:walk_under_water_one_cm\":")[1] == undefined ? "0,"
            : totalStats.split("\"minecraft:walk_under_water_one_cm\":")[1]).split(",")[0]) / 100
        let rideBoat = parseInt((totalStats.split("\"minecraft:boat_one_cm\":")[1] == undefined ? "0,"
            : totalStats.split("\"minecraft:boat_one_cm\":")[1]).split(",")[0]) / 100
        let finalScore = swiming + walkOnWater * 0.5 + walkUnderwater * 1.1 + rideBoat * 0.3

        let data = player.persistentData;
        //已经获得过的次数
        if (!data.get("ocean_score_times")) data.putInt("ocean_score_times", 0)

        let last_times = data.get("ocean_score_times")
        if (finalScore > 1000 * last_times) {
            let times = parseInt(finalScore / 1000)
            let i = times - last_times

            while (i > 0) {
                player.block.popItem(Item.of("mine_fargo:ocean_soul_stone"))
                i--
                player.setStatusMessage(i);//放这里看不出来的
            }
            data.putInt("ocean_score_times", times)
        }
    }
})

//翠绿魂石:收获作物的时候1%概率获得
BlockEvents.broken(event => {
    let { block, player } = event
    if (block.hasTag('minecraft:crops') && Math.random() < CHANCE_GREEN) {
        player.block.popItem(Item.of("mine_fargo:farmers_delight_soul_stone"))
        player.setStatusMessage(Text.green("生生不息!"));
    }
})



const FOREST_BIOME = ["forest", "flower_forest", "birch_forest", "dark_forest", "jungle", "sparse_jungle", "bamboo_jungle", "cherry_grove"];

//如果家建在这些群系(大概率是)会一直获得,一晚上掉落十多个
//森林魂石:在森林、繁花森林、桦木森林、黑森林、丛林、稀疏丛林、竹林、樱花树林群系,每隔10秒,有0.1%概率在玩家脚下生成一个。累计30分钟额外掉落一个
PlayerEvents.tick(event => {
    let { player, level } = event;
    let biome = level.getBiome(player.blockPosition()).unwrapKey().get().getPath()

    // 检查是否在目标森林群系
    let isInForest = FOREST_BIOME.some((element) => element == biome)

    let data = player.data;

    if (!data.get("forest_last_tick")) data.put("forest_last_tick", 0);
    if (!data.get("forest_timer")) data.put("forest_timer", 0);//在森林内的时间,每10秒增加一次
    let currentAge = level.getTime();
    if (isInForest) {

        // === 每10秒一次概率掉落 ===
        let lastTick = data.get("forest_last_tick");

        if (currentAge - lastTick >= 200) {
            data.put("forest_last_tick", currentAge);
            if (Math.random() < CHANCE_FOREST) {
                // 掉落物品(在玩家位置生成)
                player.block.popItem(Item.of("mine_fargo:forest_soul_stone"))
                player.setStatusMessage(Text.green("自然的馈赠!"));
            }
            data.put("forest_timer", data.get("forest_timer") + 200);
        }
    }
    else
        data.put("forest_last_tick", currentAge);


    // === 每30分钟固定掉落 ===
    let last30minTick = data.get("forest_timer");
    //player.setStatusMessage(last30minTick);
    if (last30minTick >= 36000) {
        data.put("forest_timer", data.get("forest_timer") - 36000);
        player.block.popItem(Item.of("mine_fargo:forest_soul_stone"))
        player.setStatusMessage(Text.gold("自然的恩赐!"));
    }
});


//合成表修改,主要是龙相关内容
ServerEvents.recipes(event => {
    const { tconstruct } = event.recipes;

    //龙骨的忘记了下次更新的时候补
    
    //龙血获取和浇筑,其中带有kubejs前缀的流体需要自行注册
    tconstruct.melting(Fluid.of('kubejs:fire_dragon_blood', 500), 'iceandfire:fire_dragon_heart', 1000, 40);
    tconstruct.melting(Fluid.of('kubejs:ice_dragon_blood', 500), 'iceandfire:ice_dragon_heart', 1000, 40);
    tconstruct.melting(Fluid.of('kubejs:lightning_dragon_blood', 500), 'iceandfire:lightning_dragon_heart', 1000, 40);

    tconstruct.melting(Fluid.of('kubejs:fire_dragon_blood', 100), 'iceandfire:fire_dragon_flesh', 1000, 40);
    tconstruct.melting(Fluid.of('kubejs:ice_dragon_blood', 100), 'iceandfire:ice_dragon_flesh', 1000, 40);
    tconstruct.melting(Fluid.of('kubejs:lightning_dragon_blood', 100), 'iceandfire:lightning_dragon_flesh', 1000, 40);

    tconstruct.casting_table('iceandfire:fire_dragon_blood', Fluid.of('kubejs:fire_dragon_blood', 100), 'minecraft:glass_bottle', true, 20, true);
    tconstruct.casting_table('iceandfire:ice_dragon_blood', Fluid.of('kubejs:ice_dragon_blood', 100), 'minecraft:glass_bottle', true, 20, true);
    tconstruct.casting_table('iceandfire:lightning_dragon_blood', Fluid.of('kubejs:lightning_dragon_blood', 100), 'minecraft:glass_bottle', true, 20, true);

    tconstruct.casting_table('mine_fargo:fire_dragon_blood_soul_stone', Fluid.of('kubejs:fire_dragon_blood', 500),
        'mine_fargo:dragon_bone_soul_stone', true, 20, true);
    tconstruct.casting_table('mine_fargo:ice_dragon_blood_soul_stone', Fluid.of('kubejs:ice_dragon_blood', 500),
        'mine_fargo:dragon_bone_soul_stone', true, 20, true);
    tconstruct.casting_table('mine_fargo:lightning_dragon_blood_soul_stone', Fluid.of('kubejs:lightning_dragon_blood', 500),
        'mine_fargo:dragon_bone_soul_stone', true, 20, true);





    dragonforge("fire", 3600, 'mine_fargo:dragon_bone_soul_stone', 'iceandfire:fire_dragon_blood', 'mine_fargo:fire_dragon_steel_soul_stone')
    dragonforge("ice", 3600, 'mine_fargo:dragon_bone_soul_stone', 'iceandfire:ice_dragon_blood', 'mine_fargo:ice_dragon_steel_soul_stone')
    dragonforge("lightning", 3600, 'mine_fargo:dragon_bone_soul_stone', 'iceandfire:lightning_dragon_blood', 'mine_fargo:lightning_dragon_steel_soul_stone')


    /**
     * 龙锻炉
     * @param {string} dragonForgeType 类型(fire,ice,lightning)
     * @param {number} tick 时间(20tick为1秒)
     * @param {string} input 输入物品
     * @param {string} blood 血(其实是个物品即可,即第二个物品)
     * @param {string} output 输出物品
     */
    function dragonforge(dragonForgeType, tick, input, blood, output) {
        event.custom({
            type: "iceandfire:dragonforge",
            dragon_type: dragonForgeType,
            cook_time: tick,
            input: {
                item: input
            },
            blood: {
                item: blood
            },
            result: {
                item: output
            }
        })
    }
})
//修改战利品表
LootJS.modifiers(event => {
    event.enableLogging()
    //灾变的内容
    event.addLootTableModifier("cataclysm:entities/ignis")
        .addLoot(Item.of('mine_fargo:ignis_soul_stone'))

    event.addLootTableModifier("cataclysm:entities/the_leviathan")
        .addLoot(Item.of('mine_fargo:the_leviathan_soul_stone'))

    event.addLootTableModifier("cataclysm:entities/maledictus")
        .addLoot(Item.of('mine_fargo:maledictus_soul_stone'))

    event.addLootTableModifier("cataclysm:entities/ender_guardian")
        .addLoot(Item.of('mine_fargo:ender_guardian_soul_stone'))

    event.addLootTableModifier("cataclysm:entities/ancient_remnant")
        .addLoot(Item.of('mine_fargo:ancient_remnant_soul_stone'))

    event.addLootTableModifier("cataclysm:entities/the_harbinger")
        .addLoot(Item.of('mine_fargo:the_harbinger_soul_stone'))

    event.addLootTableModifier("cataclysm:entities/netherite_monstrosity")
        .addLoot(Item.of('mine_fargo:netherite_monstrosity_soul_stone'))

    event.addLootTableModifier("cataclysm:entities/scylla")
        .addLoot(Item.of('mine_fargo:scylla_soul_stone'))


    // Ice and Fire 魂石掉落
    event.addLootTableModifier("iceandfire:entities/hydra")
        .addLoot(Item.of('mine_fargo:iaf_hydra_soul_stone'))

    event.addLootTableModifier("iceandfire:entities/siren")
        .addLoot(Item.of('mine_fargo:iaf_siren_soul_stone'))

    event.addLootTableModifier("iceandfire:entities/cyclops")
        .addLoot(Item.of('mine_fargo:cyclops_soul_stone'))

    event.addLootTableModifier("iceandfire:entities/gorgon")
        .addLoot(Item.of('mine_fargo:gorgon_soul_stone'))

    event.addLootTableModifier("iceandfire:entities/sea_serpent")
        .addLoot(Item.of('mine_fargo:sea_serpent_soul_stone'))

    //食人妖3种变体
    event.addLootTableModifier("iceandfire:entities/troll_forest")
        .addLoot(Item.of('mine_fargo:troll_soul_stone'))
    event.addLootTableModifier("iceandfire:entities/troll_frost")
        .addLoot(Item.of('mine_fargo:troll_soul_stone'))
    event.addLootTableModifier("iceandfire:entities/troll_mountain")
        .addLoot(Item.of('mine_fargo:troll_soul_stone'))


    event.addLootTableModifier("iceandfire:entities/hippocampus")
        .addLoot(Item.of('mine_fargo:hippocampus_soul_stone'))

    //死亡蠕虫3种变体
    event.addLootTableModifier("iceandfire:entities/deathworm_red_giant")
        .addLoot(Item.of('mine_fargo:death_worm_soul_stone'))
    event.addLootTableModifier("iceandfire:entities/deathworm_tan_giant")
        .addLoot(Item.of('mine_fargo:death_worm_soul_stone'))
    event.addLootTableModifier("iceandfire:entities/deathworm_white_giant")
        .addLoot(Item.of('mine_fargo:death_worm_soul_stone'))

    //海王
    event.addLootTableModifier("aquaculture:box/neptunes_bounty")
        .addLoot(Item.of('mine_fargo:neptunium_soul_stone'))
})
//下面是超然之魂下属的魂石,所有这些魂石都可以去任务商店买,锚定魂石(不知道有什么用)和修复魂石(op)只能任务获取

//磁铁魂石:捡起物品时0.1%概率获得,无保底
//由于是检测背包变化,所以从任何gui里拿东西到背包也算
PlayerEvents.inventoryChanged(event => {
    let { player } = event;
//这个概率还是可以的,一晚上出了三四个,感觉可以再低一点1
    if (Math.random() < CHANCE_MAGNET) {
        player.block.popItem(Item.of("mine_fargo:magnet_soul_stone"))
        player.setStatusMessage(Text.blue("Mag").append(Text.red("net!")));
    }
})
const EnigmaticItems = Java.loadClass("com.aizistral.enigmaticlegacy.registries.EnigmaticItems")

EntityEvents.death(event => {
    let { player, source, entity } = event;

    if (source.getActual().type == "minecraft:player")
        player = source.getActual()//为player重新赋值
    else return

    //危险魂石:杀死任意生物有0.1%获得,无保底
    if (Math.random() < CHANCE_DANGER) {
        entity.block.popItem(Item.of("mine_fargo:hazard_soul_stone"))
        player.setStatusMessage(Text.red("危险!"))
    }
    //替死魂石:在灵魂破碎状态(灵魂水晶不满)且身上有灵魂窃取buff的时候击杀任意生物100%获得
    if (EnigmaticItems.SOUL_CRYSTAL.getLostCrystals(player) > 0 && player.hasEffect("alexsmobs:soulsteal")) {
        entity.block.popItem(Item.of("mine_fargo:undying_soul_stone"))
    }
})
//金果魂石:每次吃(附魔)金苹果有(15%)5%概率获得,无保底
ItemEvents.foodEaten(event => {
    let { player } = event;
    if (event.item.id == "minecraft:golden_apple") {
        if (Math.random() < CHANCE_GOLDEN_APPLE) {
            player.block.popItem(Item.of('mine_fargo:enchanted_golden_apple_soul_stone'))
            player.setStatusMessage(Text.gold("金苹果!"))
        }
    }
    if (event.item.id == "minecraft:enchanted_golden_apple") {
        if (Math.random() < CHANCE_GOLDEN_APPLE * 3) {
            player.block.popItem(Item.of('mine_fargo:enchanted_golden_apple_soul_stone'))
            player.setStatusMessage(Text.gold("金苹果!"))
        }
    }
})
//潮水魂石:身上有潮涌buff时,每三分钟获取一个
PlayerEvents.tick(event => {
    let { player, level } = event;
    if (!player.data.get("conduit_timer")) player.data.put("conduit_timer", 0)//计数器,记录下一次应该获取潮水魂石的时间


    let now = level.getTime()
    if (player.hasEffect("minecraft:conduit_power")) {
        let timer = player.data.get("conduit_timer")

        if (timer == 0)//获取buff的第一刻
            player.data.put("conduit_timer", now + 3600)
        else if (now >= timer) {
            player.block.popItem(Item.of("mine_fargo:water_soul_stone"))
            player.data.put("conduit_timer", now + 3600)
            player.setStatusMessage(Text.blue("潮涌!"))
        }
    }
    else
        player.data.put("conduit_timer", 0)


    //初级的代码,效率低
    // if (player.hasEffect("minecraft:conduit_power")) {
    //     //临时变量,记录上一次更新计时器的世界时间
    //     let timer = player.data.get("conduit_timer")
    //     timer++
    //     if (timer >= 3600) {
    //         player.block.popItem(Item.of("mine_fargo:water_soul_stone"))
    //         timer -= 3600
    //     }
    //     player.data.put("conduit_timer", timer)
    // }
    // else
    //     player.data.put("conduit_timer", 0)
})

//轮子,重复命名比较多,然后其实有没用到的,我以为我会用但是没有,没用到的写完之后就没更新了。因为名字都长得比较像所以也都没改


/**
 * 重复击杀生物掉落指定物品(计数器持久化在 player.data 中)
 * @param {Internal.LivingEntityDeathEventJS} event 
 * @param {string} target 生物ID,如 "minecraft:zombified_piglin"
 * @param {number} times 每多少次掉落一个物品
 * @param {string} key 存储在 player.data 中的计数器键名,如 "nether_count"
 * @param {string} item 掉落物品ID
 * @param {boolean} prompt 是否显示当前计数
 */
function multipleKillCounter(event, target, times, key, item, prompt) {
    let { entity, source, player } = event;
    if (source.getActual().type == "minecraft:player")
        player = source.getActual()//为player重新赋值
    else player = null

    if (entity.type !== target) return;



    // 获取当前计数,若不存在则初始化为 0
    let count = player.data.get(key);
    if (isNaN(count)) count = 0;

    count++;

    // 显示计数(可选)
    if (prompt) {
        player.setStatusMessage(Text.green(`${key}: ${count}`));
    }

    // 检查是否达到掉落条件
    if (count >= times) {
        // 掉落物品
        entity.block.popItem(Item.of(item));
        // 减去对应次数,保留余数
        count -= times;
    }

    // 将新计数写回 player.data
    player.data.put(key, count);
}

/**
 * 用于设置批量类型的生物击杀奖励
 * @param {Internal.LivingEntityDeathEventJS} event 
 * @param {Internal.Player} player 
 * @param {string} target tag或者mod,不带#
 * @param {number} times 
 * @param {string} key 
 * @param {string} item 
 * @param {boolean} prompt 
 * @param {boolean} tagOrMod true表示tag,false表示mod
 */
function multipleKillCounterTag(event, player, target, times, key, item, prompt, tagOrMod) {
    let { entity } = event;
    if (tagOrMod) {
        //tag匹配模式,如果没有对应tag直接退出
        if (!entity.hasTag(target))
            return
    } else {
        //mod匹配模式,type是modid:name的格式
        if (!entity.getType().startsWith(target))
            return
    }



    // 获取当前计数,若不存在则初始化为 0
    let count = player.data.get(key);
    if (isNaN(count)) count = 0;

    count++;

    // 显示计数(可选)
    if (prompt) {
        player.setStatusMessage(Text.green(`${key}: ${count}`));
    }

    // 检查是否达到掉落条件
    if (count >= times) {
        // 掉落物品
        entity.block.popItem(Item.of(item));
        // 减去对应次数,保留余数
        count -= times;
    }

    // 将新计数写回 player.data
    player.data.put(key, count);
}

/**
 * 玩家击杀指定列表中的生物有概率获取物品
 * @param {Internal.LivingEntityDeathEventJS} event -
 * @param {string[]} targetList 一个string数组,包含所有目标
 * @param {number} chance 概率
 * @param {string} key 存储在 player.data 中的计数器键名,如 "nether_count"
 * @param {string} item 物品id
 * @param {boolean} guarantee 是否有保底(保底数字为1/chance)
 * @returns 
 */
function multipleKillCounterList(event, targetList, chance, key, item, guarantee) {
    let { entity, source, player } = event;
    if (source.getActual().type == "minecraft:player")
        player = source.getActual()//为player重新赋值
    else player = null

    if (targetList.indexOf(entity.type) == -1) return;

    if (Math.random() < chance)
        player.block.popItem(Item.of(item))

    // 获取当前计数,若不存在则初始化为 0
    let count = player.data.get(key);
    let times = 1 / chance;
    if (isNaN(count)) count = 0;
    count++;
    // 检查是否达到掉落条件
    if (guarantee && count >= times) {
        // 掉落物品
        entity.block.popItem(Item.of(item));
        // 减去对应次数,保留余数
        count -= times;
    }
    // 将新计数写回 player.data
    player.data.put(key, count);
}

/**
 * 玩家击杀怪物类型的生物有概率获取物品
 * @param {Internal.LivingEntityDeathEventJS} event -
 * @param {Internal.MobType} mobType 怪物类型
 * @param {number} chance 概率
 * @param {string} key 存储在 player.data 中的计数器键名,如 "nether_count"
 * @param {string} item 物品id
 * @param {boolean} guarantee 是否有保底(保底数字为1/chance)
 * @returns 
 */
function multipleKillCounterByMobType(event, mobType, chance, key, item, guarantee) {
    let { entity, source, player } = event;
    if (source.getActual().type == "minecraft:player")
        player = source.getActual()//为player重新赋值
    else player = null

    if (entity.mobType !== mobType) return;

    if (Math.random() < chance)
        player.block.popItem(Item.of(item))

    // 获取当前计数,若不存在则初始化为 0
    let count = player.data.get(key);
    let times = 1 / chance;
    if (isNaN(count)) count = 0;
    count++;
    // 检查是否达到掉落条件
    if (guarantee && count >= times) {
        // 掉落物品
        entity.block.popItem(Item.of(item));
        // 减去对应次数,保留余数
        count -= times;
    }
    // 将新计数写回 player.data
    player.data.put(key, count);
}