Foxyas / Changed-Addon-Rework

MIT License
6 stars 6 forks source link

NullPointerException #23

Closed gengyoubo closed 5 days ago

gengyoubo commented 6 days ago

crash-2024-11-20_17.39.42-client.txt

package net.foxyas.changedaddon.mixins;

import net.foxyas.changedaddon.ability.ChangedAddonAbilitys;
import net.foxyas.changedaddon.configuration.ChangedAddonConfigsConfiguration;
import net.ltxprogrammer.changed.entity.variant.TransfurVariantInstance;
import net.ltxprogrammer.changed.init.ChangedAbilities;
import net.ltxprogrammer.changed.process.ProcessTransfur;
import net.minecraft.core.BlockPos;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.BlockTags;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.EntityCollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

@Mixin(BlockBehaviour.class)
public abstract class BlockMixin {

    @Inject(method = "getCollisionShape", at = @At("HEAD"), cancellable = true)
    private void getCollisionModShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext context, CallbackInfoReturnable<VoxelShape> cir) {
        if (context instanceof EntityCollisionContext entityContext) {
            Entity collidingEntity = entityContext.getEntity();

            if (collidingEntity != null && state.is(BlockTags.create(new ResourceLocation("changed_addon:passable_blocks")))) {
                // Verifica se a entidade é um jogador
                if (collidingEntity instanceof Player player) {
                    // Verifica uma condição específica do jogador (no caso, ProcessTransfur)
                    if (ProcessTransfur.isPlayerLatex(player)) {
                        TransfurVariantInstance<?> transfurVariantInstance = ProcessTransfur.getPlayerTransfurVariant(player);
                        if (transfurVariantInstance.getAbilityInstance(ChangedAbilities.GRAB_ENTITY_ABILITY.get()) == null || transfurVariantInstance.getAbilityInstance(ChangedAbilities.GRAB_ENTITY_ABILITY.get()).grabbedEntity != null){
                            return;
                        }
                        if (ChangedAddonConfigsConfiguration.CAN_PASS_THROUGH_BLOCKS.get()){
                            cir.setReturnValue(Shapes.empty());
                        }
                        transfurVariantInstance.ifHasAbility(ChangedAddonAbilitys.SOFTEN_ABILITY.get(), Instance -> {
                            if (Instance.isActivate()){
                                // Se for um jogador Latex, permite que ele atravesse a barra de ferro (forma vazia)
                                cir.setReturnValue(Shapes.empty()); // Colisão desativada para jogadores Latex
                            }
                        });
                        //SoftenAbilityInstance ability = ProcessTransfur.getPlayerTransfurVariant(player).getAbilityInstance(ChangedAddonAbilitys.SOFTEN_ABILITY.get());
                    }
                }
            }
        }
    }
}

I guess there is no reference to this.hasCollision after the ruture so there is a null value. The best way is to process the return value, like:

 cir.setReturnValue(this.hasCollision ? p_60572_.getShape(p_60573_, p_60574_) : Shapes.empty());
gengyoubo commented 6 days ago
@Shadow protected final boolean hasCollision;
    protected BlockMixin(boolean hasCollision) {
        this.hasCollision = hasCollision;
    }
    @Inject(method = "getCollisionShape", at = @At("HEAD"), cancellable = true)
    private void getCollisionModShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext context, CallbackInfoReturnable<VoxelShape> cir) {
        if (context instanceof EntityCollisionContext entityContext) {
            Entity collidingEntity = entityContext.getEntity();

            if (collidingEntity != null && state.is(BlockTags.create(new ResourceLocation("changed_addon:passable_blocks")))) {
                // Verifica se a entidade é um jogador
                if (collidingEntity instanceof Player player) {
                    // Verifica uma condição específica do jogador (no caso, ProcessTransfur)
                    if (ProcessTransfur.isPlayerLatex(player)) {
                        TransfurVariantInstance<?> transfurVariantInstance = ProcessTransfur.getPlayerTransfurVariant(player);
                        // Se a habilidade GRAB_ENTITY for nula ou a entidade já foi agarrada, retorna a colisão padrão
                        if (transfurVariantInstance.getAbilityInstance(ChangedAbilities.GRAB_ENTITY_ABILITY.get()) == null || transfurVariantInstance.getAbilityInstance(ChangedAbilities.GRAB_ENTITY_ABILITY.get()).grabbedEntity != null) {
                            cir.setReturnValue(this.hasCollision ? state.getShape(world, pos) : Shapes.empty()); 
                        }
                        // Se a configuração permitir, o jogador pode atravessar o bloco
                        if (ChangedAddonConfigsConfiguration.CAN_PASS_THROUGH_BLOCKS.get()) {
                            cir.setReturnValue(Shapes.empty()); // Colisão desativada
                        }
                        // Verifica se o jogador tem a habilidade SOFTEN ativa
                        transfurVariantInstance.ifHasAbility(ChangedAddonAbilitys.SOFTEN_ABILITY.get(), instance -> {
                            if (instance.isActivate()) {
                                // Se a habilidade SOFTEN estiver ativa, permite que o jogador atravesse o bloco
                                cir.setReturnValue(Shapes.empty()); // Colisão desativada
                            }
                        });
                    }
                }
            }
        }
        cir.setReturnValue(this.hasCollision ? state.getShape(world, pos) : Shapes.empty());
    }
Foxyas commented 5 days ago
@Shadow protected final boolean hasCollision;
    protected BlockMixin(boolean hasCollision) {
        this.hasCollision = hasCollision;
    }
    @Inject(method = "getCollisionShape", at = @At("HEAD"), cancellable = true)
    private void getCollisionModShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext context, CallbackInfoReturnable<VoxelShape> cir) {
        if (context instanceof EntityCollisionContext entityContext) {
            Entity collidingEntity = entityContext.getEntity();

            if (collidingEntity != null && state.is(BlockTags.create(new ResourceLocation("changed_addon:passable_blocks")))) {
                // Verifica se a entidade é um jogador
                if (collidingEntity instanceof Player player) {
                    // Verifica uma condição específica do jogador (no caso, ProcessTransfur)
                    if (ProcessTransfur.isPlayerLatex(player)) {
                        TransfurVariantInstance<?> transfurVariantInstance = ProcessTransfur.getPlayerTransfurVariant(player);
                        // Se a habilidade GRAB_ENTITY for nula ou a entidade já foi agarrada, retorna a colisão padrão
                        if (transfurVariantInstance.getAbilityInstance(ChangedAbilities.GRAB_ENTITY_ABILITY.get()) == null || transfurVariantInstance.getAbilityInstance(ChangedAbilities.GRAB_ENTITY_ABILITY.get()).grabbedEntity != null) {
                            cir.setReturnValue(this.hasCollision ? state.getShape(world, pos) : Shapes.empty()); 
                        }
                        // Se a configuração permitir, o jogador pode atravessar o bloco
                        if (ChangedAddonConfigsConfiguration.CAN_PASS_THROUGH_BLOCKS.get()) {
                            cir.setReturnValue(Shapes.empty()); // Colisão desativada
                        }
                        // Verifica se o jogador tem a habilidade SOFTEN ativa
                        transfurVariantInstance.ifHasAbility(ChangedAddonAbilitys.SOFTEN_ABILITY.get(), instance -> {
                            if (instance.isActivate()) {
                                // Se a habilidade SOFTEN estiver ativa, permite que o jogador atravesse o bloco
                                cir.setReturnValue(Shapes.empty()); // Colisão desativada
                            }
                        });
                    }
                }
            }
        }
        cir.setReturnValue(this.hasCollision ? state.getShape(world, pos) : Shapes.empty());
    }

I forgot that return; in mixin does not automatically cancel so i can just cancel manually after the logic match I think that cancel the mixin would be the best Solution because that would make the value return the original one

Foxyas commented 5 days ago

cir.cancel()