minecraft-src/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java
2025-07-04 01:41:11 +03:00

148 lines
4.7 KiB
Java

package net.minecraft.world.entity.ai.goal;
import net.minecraft.core.BlockPos;
import net.minecraft.core.SectionPos;
import net.minecraft.core.particles.ItemParticleOption;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.RandomSource;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.entity.PathfinderMob;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.GameRules;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.status.ChunkStatus;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.Nullable;
public class RemoveBlockGoal extends MoveToBlockGoal {
private final Block blockToRemove;
private final Mob removerMob;
private int ticksSinceReachedGoal;
private static final int WAIT_AFTER_BLOCK_FOUND = 20;
public RemoveBlockGoal(Block blockToRemove, PathfinderMob removerMob, double speedModifier, int searchRange) {
super(removerMob, speedModifier, 24, searchRange);
this.blockToRemove = blockToRemove;
this.removerMob = removerMob;
}
@Override
public boolean canUse() {
if (!this.removerMob.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) {
return false;
} else if (this.nextStartTick > 0) {
this.nextStartTick--;
return false;
} else if (this.findNearestBlock()) {
this.nextStartTick = reducedTickDelay(20);
return true;
} else {
this.nextStartTick = this.nextStartTick(this.mob);
return false;
}
}
@Override
public void stop() {
super.stop();
this.removerMob.fallDistance = 1.0F;
}
@Override
public void start() {
super.start();
this.ticksSinceReachedGoal = 0;
}
public void playDestroyProgressSound(LevelAccessor level, BlockPos pos) {
}
public void playBreakSound(Level level, BlockPos pos) {
}
@Override
public void tick() {
super.tick();
Level level = this.removerMob.level();
BlockPos blockPos = this.removerMob.blockPosition();
BlockPos blockPos2 = this.getPosWithBlock(blockPos, level);
RandomSource randomSource = this.removerMob.getRandom();
if (this.isReachedTarget() && blockPos2 != null) {
if (this.ticksSinceReachedGoal > 0) {
Vec3 vec3 = this.removerMob.getDeltaMovement();
this.removerMob.setDeltaMovement(vec3.x, 0.3, vec3.z);
if (!level.isClientSide) {
double d = 0.08;
((ServerLevel)level)
.sendParticles(
new ItemParticleOption(ParticleTypes.ITEM, new ItemStack(Items.EGG)),
blockPos2.getX() + 0.5,
blockPos2.getY() + 0.7,
blockPos2.getZ() + 0.5,
3,
(randomSource.nextFloat() - 0.5) * 0.08,
(randomSource.nextFloat() - 0.5) * 0.08,
(randomSource.nextFloat() - 0.5) * 0.08,
0.15F
);
}
}
if (this.ticksSinceReachedGoal % 2 == 0) {
Vec3 vec3 = this.removerMob.getDeltaMovement();
this.removerMob.setDeltaMovement(vec3.x, -0.3, vec3.z);
if (this.ticksSinceReachedGoal % 6 == 0) {
this.playDestroyProgressSound(level, this.blockPos);
}
}
if (this.ticksSinceReachedGoal > 60) {
level.removeBlock(blockPos2, false);
if (!level.isClientSide) {
for (int i = 0; i < 20; i++) {
double d = randomSource.nextGaussian() * 0.02;
double e = randomSource.nextGaussian() * 0.02;
double f = randomSource.nextGaussian() * 0.02;
((ServerLevel)level).sendParticles(ParticleTypes.POOF, blockPos2.getX() + 0.5, blockPos2.getY(), blockPos2.getZ() + 0.5, 1, d, e, f, 0.15F);
}
this.playBreakSound(level, blockPos2);
}
}
this.ticksSinceReachedGoal++;
}
}
@Nullable
private BlockPos getPosWithBlock(BlockPos pos, BlockGetter level) {
if (level.getBlockState(pos).is(this.blockToRemove)) {
return pos;
} else {
BlockPos[] blockPoss = new BlockPos[]{pos.below(), pos.west(), pos.east(), pos.north(), pos.south(), pos.below().below()};
for (BlockPos blockPos : blockPoss) {
if (level.getBlockState(blockPos).is(this.blockToRemove)) {
return blockPos;
}
}
return null;
}
}
@Override
protected boolean isValidTarget(LevelReader level, BlockPos pos) {
ChunkAccess chunkAccess = level.getChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ()), ChunkStatus.FULL, false);
return chunkAccess == null
? false
: chunkAccess.getBlockState(pos).is(this.blockToRemove) && chunkAccess.getBlockState(pos.above()).isAir() && chunkAccess.getBlockState(pos.above(2)).isAir();
}
}