package com.thebrokenrail.twine.mixin; import com.thebrokenrail.twine.component.StageDataComponent; import com.thebrokenrail.twine.entity.ExplodeArtificialBlockGoal; import com.thebrokenrail.twine.entity.FleeEndRodGoal; import com.thebrokenrail.twine.entity.FollowPassiveEntityGoal; import com.thebrokenrail.twine.entity.StandOnGlowingObsidianGoal; import com.thebrokenrail.twine.util.StageUtil; import net.minecraft.entity.EntityType; import net.minecraft.entity.ai.goal.FollowTargetGoal; import net.minecraft.entity.ai.goal.GoalSelector; import net.minecraft.entity.mob.CreeperEntity; import net.minecraft.entity.mob.MobEntity; import net.minecraft.entity.mob.MobEntityWithAi; import net.minecraft.entity.mob.Monster; import net.minecraft.entity.passive.IronGolemEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import java.util.Random; @SuppressWarnings("ConstantConditions") @Mixin(MobEntity.class) public class MixinMobEntity { @Shadow @Final protected GoalSelector targetSelector; @Shadow @Final protected GoalSelector goalSelector; @Inject(at = @At("RETURN"), method = "") public void initGoals(EntityType entityType, World world, CallbackInfo info) { if (world != null && !world.isClient()) { if (this instanceof Monster) { if ((Object) this instanceof MobEntityWithAi) { goalSelector.add(1, new StandOnGlowingObsidianGoal((MobEntityWithAi) (Object) this)); goalSelector.add(3, new FleeEndRodGoal((MobEntityWithAi) (Object) this)); if ((Object) this instanceof CreeperEntity) { goalSelector.add(3, new ExplodeArtificialBlockGoal((MobEntityWithAi) (Object) this)); } } targetSelector.add(2, new FollowPassiveEntityGoal((MobEntity) (Object) this)); } else if ((Object) this instanceof IronGolemEntity) { targetSelector.add(3, new FollowTargetGoal<>((IronGolemEntity) (Object) this, PlayerEntity.class, 10, true, false, entity -> { StageDataComponent component = StageDataComponent.getFromWorld((ServerWorld) ((IronGolemEntity) (Object) this).getEntityWorld()); BlockPos blockPos = ((IronGolemEntity) (Object) this).getBlockPos(); int stage = component.findEffectiveStageOfChunk((ServerWorld) (((IronGolemEntity) (Object) this).getEntityWorld()), blockPos); return stage >= StageUtil.IRON_GOLEMS_TARGET_PLAYERS && !((IronGolemEntity) (Object) this).isPlayerCreated(); })); } } } @Inject(at = @At("HEAD"), method = "isInDaylight", cancellable = true) public void isInDaylight(CallbackInfoReturnable info) { if (!((MobEntity) (Object) this).getEntityWorld().isClient()) { StageDataComponent component = StageDataComponent.getFromWorld((ServerWorld) ((MobEntity) (Object) this).getEntityWorld()); BlockPos blockPos = ((MobEntity) (Object) this).getBlockPos(); int stage = component.findEffectiveStageOfChunk((ServerWorld) ((MobEntity) (Object) this).getEntityWorld(), blockPos); if (stage >= StageUtil.MOBS_NO_LONGER_BURN_IN_SUNLIGHT) { info.setReturnValue(false); } } } @Redirect(at = @At(value = "INVOKE", target = "Ljava/util/Random;nextFloat()F", ordinal = 0), method = "initEquipment", allow = 1) public float initEquipment(Random random) { StageDataComponent component = StageDataComponent.getFromWorld((ServerWorld) ((MobEntity) (Object) this).getEntityWorld()); BlockPos blockPos = ((MobEntity) (Object) this).getBlockPos(); int stage = component.findEffectiveStageOfChunk((ServerWorld) ((MobEntity) (Object) this).getEntityWorld(), blockPos); if (stage >= StageUtil.MOBS_GUARANTEED_ARMOR) { return -1f; } else { return random.nextFloat(); } } }