HexMod icon indicating copy to clipboard operation
HexMod copied to clipboard

[Bug?] Break Block does not call onBreak of broken blocks

Open walksanatora opened this issue 2 years ago • 8 comments

so in Hexxy Dimensions I have a block that when broken checks the player and sends them back to the overworld but break block does not pass that (or some other way my blocks onBreakBlock method is not being called

walksanatora avatar Dec 02 '23 07:12 walksanatora

can you please provide the minimal steps/code necessary to reproduce the issue?

object-Object avatar Dec 02 '23 08:12 object-Object

made a block with

class TestBlock(set: Settings) : Block(set) {
    override fun onBreak(world: World, pos: BlockPos?, state: BlockState?, player: PlayerEntity) {
        super.onBreak(world, pos, state, player)
        println("world: %s\npos: %s\nstate: %s\nplayer: %s".format(
            world,pos,state,player
        ))
    }
}

when I break with my fist the world,pos,state,player are printed to console when I break with BreakBlock it fails

also also checked with /setblock and /fill and same effect occurs (no output)

walksanatora avatar Dec 03 '23 05:12 walksanatora

Please post all of the relevant versions (game, modloader, hex, etc) and the modlist.

object-Object avatar Jan 11 '24 02:01 object-Object

1.20.1, fabric, hexcasting 0.11.1-7-pre-609, patchouli 1.20.1-84 paucal 0.6.0-pre-118 cloth config 11.1.118 cardinal componenets api 5.2.1 hexxy-dimensions 1.2.1

this could probally be fixed with a

if (env.caster is ServerPlayer) {
    blockstate.block.onBreak(env.world,pos,blockstate,env.caster
}

after the call to env.world.destroyBlock

walksanatora avatar Jan 19 '24 03:01 walksanatora

onBreak (named playerWillDestroy in the mojMap) seems to be specifically for when players break blocks, triggering things like piglin getting angry, ensuring shulker boxes are still dropped if the player is in creative, etc. I think it would break things elsewhere to add this call (example: if the player casts break block in creative shulker boxes will drop twice, once from the playerWillDestroy call and once from the normal loot drop method).

Talia-12 avatar Feb 05 '24 13:02 Talia-12

then perhaps some sort of interface for HexcastingBreakAware so you can make a block aware of onBreak manually

walksanatora avatar Feb 05 '24 16:02 walksanatora

idea for HexcastingBreakAware intereface would be:

interface HexcastingBreakAwareBlock {
     void onHexcastingBreak(CastingEnvironment env, BlockPos pos, BlockState state)
}

walksanatora avatar Feb 05 '24 16:02 walksanatora

For comparison, this is how Psi does it: https://github.com/VazkiiMods/Psi/blob/3f9806bcb00caf1a17a24f2052161649d4d4a33c/src/main/java/vazkii/psi/common/spell/trick/block/PieceTrickBreakBlock.java#L106-L111

Alternatively, here's how net.minecraft.server.level.ServerPlayerGameMode#destroyBlock works - maybe we could do something similar?

    public boolean destroyBlock(BlockPos pos) {
        BlockState blockState = this.level.getBlockState(pos);
        if (!this.player.getMainHandItem().getItem().canAttackBlock(blockState, this.level, pos, this.player)) {
            return false;
        } else {
            BlockEntity blockEntity = this.level.getBlockEntity(pos);
            Block block = blockState.getBlock();
            if (block instanceof GameMasterBlock && !this.player.canUseGameMasterBlocks()) {
                this.level.sendBlockUpdated(pos, blockState, blockState, 3);
                return false;
            } else if (this.player.blockActionRestricted(this.level, pos, this.gameModeForPlayer)) {
                return false;
            } else {
                block.playerWillDestroy(this.level, pos, blockState, this.player);
                boolean bl = this.level.removeBlock(pos, false);
                if (bl) {
                    block.destroy(this.level, pos, blockState);
                }

                if (this.isCreative()) {
                    return true;
                } else {
                    ItemStack itemStack = this.player.getMainHandItem();
                    ItemStack itemStack2 = itemStack.copy();
                    boolean bl2 = this.player.hasCorrectToolForDrops(blockState);
                    itemStack.mineBlock(this.level, blockState, pos, this.player);
                    if (bl && bl2) {
                        block.playerDestroy(this.level, this.player, pos, blockState, blockEntity, itemStack2);
                    }

                    return true;
                }
            }
        }
    }

object-Object avatar Jun 14 '24 22:06 object-Object