codetaylor / dropt-1.12

Flexible block drop strategies.
https://minecraft.curseforge.com/projects/dropt
Other
6 stars 2 forks source link

Forestry's Apatite Ore / Evilcraft's Dark Ore continue to drop their experience #21

Closed KAfable closed 6 years ago

KAfable commented 6 years ago

Given this JSON: https://hastebin.com/rocucewulu.json, I'm trying to make blocks silk touch drop their ores and for all of the ores listed except Forestry's Apatite (forestry:resources:0) and Evilcraft's Dark Ores, those still continue to drop experience. Any insight on this?

If nothing can be done on Dropt's end, what should I be recommending to the Evilcraft/Forestry devs to change about their ore blocks so it'll respect Dropt's changes?

Thanks again btw for your earlier changes with the XP replace strategy, it's been helping a lot with my planned ore processing so far.

codetaylor commented 6 years ago

Dropt can't do anything about those blocks dropping XP because they spawn the XP into the world directly.

Both Forestry and EvilCraft call Block#dropXpOnBlockBreak(World, BlockPos, int) to drop the XP which spawns it into the world directly.

https://github.com/ForestryMC/ForestryMC/blob/mc-1.12/src/main/java/forestry/core/blocks/BlockResourceOre.java#L66

https://github.com/CyclopsMC/EvilCraft/blob/master-1.12/src/main/java/org/cyclops/evilcraft/block/DarkOre.java#L100

Dropt intercepts XP in the BlockEvent.BreakEvent event, which gets its XP by calling Block#getExpDrop(IBlockState, IBlockAccess, BlockPos, int). For Dropt to be able to manipulate a block's XP drop, the mod's block must override Block#getExpDrop and return the XP amount from that method.

This is how vanilla does it:

    @Override
    public int getExpDrop(IBlockState state, IBlockAccess world, BlockPos pos, int fortune)
    {
        Random rand = world instanceof World ? ((World)world).rand : new Random();
        if (this.getItemDropped(state, rand, fortune) != Item.getItemFromBlock(this))
        {
            int i = 0;

            if (this == Blocks.COAL_ORE)
            {
                i = MathHelper.getInt(rand, 0, 2);
            }
            else if (this == Blocks.DIAMOND_ORE)
            {
                i = MathHelper.getInt(rand, 3, 7);
            }
            else if (this == Blocks.EMERALD_ORE)
            {
                i = MathHelper.getInt(rand, 3, 7);
            }
            else if (this == Blocks.LAPIS_ORE)
            {
                i = MathHelper.getInt(rand, 2, 5);
            }
            else if (this == Blocks.QUARTZ_ORE)
            {
                i = MathHelper.getInt(rand, 2, 5);
            }

            return i;
        }
        return 0;
    }

Block#dropXpOnBlockBreak(World, BlockPos, int) is called from the Block#tryHarvestBlock(BlockPos) method after the block break event is processed. The XP amount from the block break event is passed into the call to Block#dropXpOnBlockBreak(World, BlockPos, int) to actually spawn the XP in the world.

I would recommend that mod blocks override the Block#getExpDrop method instead of calling the other method directly. It seems more correct, if there even is such a thing in modded MC. ¯\_(ツ)_/¯