package com.thebrokenrail.twine.entity; import com.thebrokenrail.twine.Twine; import com.thebrokenrail.twine.component.StageDataComponent; import com.thebrokenrail.twine.util.StageUtil; import net.minecraft.block.BlockState; import net.minecraft.entity.ai.goal.MoveToTargetPosGoal; import net.minecraft.entity.mob.CreeperEntity; import net.minecraft.entity.mob.MobEntityWithAi; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; import net.minecraft.world.WorldView; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.ChunkStatus; public class ExplodeArtificialBlockGoal extends MoveToTargetPosGoal { public ExplodeArtificialBlockGoal(MobEntityWithAi mob) { super(mob, 1d, Twine.AI_RANGE, Twine.AI_MAX_Y_DIFFERENCE); } @Override protected boolean isTargetPos(WorldView world, BlockPos pos) { Chunk chunk = world.getChunk(pos.getX() >> 4, pos.getZ() >> 4, ChunkStatus.FULL, false); if (chunk == null) { return false; } else { return chunk.getBlockState(pos).isOpaqueFullCube(world, pos) && chunk.getBlockState(pos.up()).isAir() && chunk.getBlockState(pos.up(2)).isAir() && (isArtificial(world, chunk, pos) || isArtificial(world, chunk, pos.up().north()) || isArtificial(world, chunk, pos.up().south()) || isArtificial(world, chunk, pos.up().east()) || isArtificial(world, chunk, pos.up().west())); } } private boolean isArtificial(WorldView world, Chunk chunk, BlockPos pos) { ChunkPos newPos = new ChunkPos(pos.getX() >> 4, pos.getZ() >> 4); if (!chunk.getPos().equals(newPos)) { chunk = world.getChunk(newPos.x, newPos.z, ChunkStatus.FULL, false); if (chunk == null) { return false; } } BlockState state = chunk.getBlockState(pos); return state != null && (state.isIn(Twine.ARTIFICIAL_BLOCKS_TAG) || state.getLuminance() > 12); } @Override public double getDesiredSquaredDistanceToTarget() { return 2d; } @Override public void tick() { super.tick(); if (this.hasReached() && mob instanceof CreeperEntity) { ((CreeperEntity) mob).setIgnited(); } } @Override public boolean canStart() { StageDataComponent component = StageDataComponent.getFromWorld((ServerWorld) mob.getEntityWorld()); BlockPos pos = mob.getBlockPos(); int stage = component.findEffectiveStageOfChunk((ServerWorld) mob.getEntityWorld(), pos); return stage >= StageUtil.CREEPERS_TARGET_ARTIFICIAL_BLOCKS && super.canStart(); } @Override protected boolean findTargetPos() { if (targetPos != null && isTargetPos(mob.world, targetPos)) { return true; } else { return super.findTargetPos(); } } }