Code/net/minecraft/world/entity/ai/behavior/RamTarget.java

123 lines
6.4 KiB
Java

package net.minecraft.world.entity.ai.behavior;
import com.google.common.collect.ImmutableMap;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.ToDoubleFunction;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.sounds.SoundSource;
import net.minecraft.tags.BlockTags;
import net.minecraft.util.Mth;
import net.minecraft.util.valueproviders.UniformInt;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.ai.Brain;
import net.minecraft.world.entity.ai.attributes.Attributes;
import net.minecraft.world.entity.ai.memory.MemoryModuleType;
import net.minecraft.world.entity.ai.memory.MemoryStatus;
import net.minecraft.world.entity.ai.memory.WalkTarget;
import net.minecraft.world.entity.ai.targeting.TargetingConditions;
import net.minecraft.world.entity.animal.goat.Goat;
import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.minecraft.world.phys.Vec3;
public class RamTarget extends Behavior<Goat> {
public static final int TIME_OUT_DURATION = 200;
public static final float RAM_SPEED_FORCE_FACTOR = 1.65F;
private final Function<Goat, UniformInt> getTimeBetweenRams;
private final TargetingConditions ramTargeting;
private final float speed;
private final ToDoubleFunction<Goat> getKnockbackForce;
private Vec3 ramDirection;
private final Function<Goat, SoundEvent> getImpactSound;
private final Function<Goat, SoundEvent> getHornBreakSound;
public RamTarget(
Function<Goat, UniformInt> p_217342_,
TargetingConditions p_217343_,
float p_217344_,
ToDoubleFunction<Goat> p_217345_,
Function<Goat, SoundEvent> p_217346_,
Function<Goat, SoundEvent> p_217347_
) {
super(ImmutableMap.of(MemoryModuleType.RAM_COOLDOWN_TICKS, MemoryStatus.VALUE_ABSENT, MemoryModuleType.RAM_TARGET, MemoryStatus.VALUE_PRESENT), 200);
this.getTimeBetweenRams = p_217342_;
this.ramTargeting = p_217343_;
this.speed = p_217344_;
this.getKnockbackForce = p_217345_;
this.getImpactSound = p_217346_;
this.getHornBreakSound = p_217347_;
this.ramDirection = Vec3.ZERO;
}
protected boolean checkExtraStartConditions(ServerLevel p_217349_, Goat p_217350_) {
return p_217350_.getBrain().hasMemoryValue(MemoryModuleType.RAM_TARGET);
}
protected boolean canStillUse(ServerLevel p_217352_, Goat p_217353_, long p_217354_) {
return p_217353_.getBrain().hasMemoryValue(MemoryModuleType.RAM_TARGET);
}
protected void start(ServerLevel p_217359_, Goat p_217360_, long p_217361_) {
BlockPos blockpos = p_217360_.blockPosition();
Brain<?> brain = p_217360_.getBrain();
Vec3 vec3 = brain.getMemory(MemoryModuleType.RAM_TARGET).get();
this.ramDirection = new Vec3(blockpos.getX() - vec3.x(), 0.0, blockpos.getZ() - vec3.z()).normalize();
brain.setMemory(MemoryModuleType.WALK_TARGET, new WalkTarget(vec3, this.speed, 0));
}
protected void tick(ServerLevel p_217366_, Goat p_217367_, long p_217368_) {
List<LivingEntity> list = p_217366_.getNearbyEntities(LivingEntity.class, this.ramTargeting, p_217367_, p_217367_.getBoundingBox());
Brain<?> brain = p_217367_.getBrain();
if (!list.isEmpty()) {
LivingEntity livingentity = list.get(0);
DamageSource damagesource = p_217366_.damageSources().noAggroMobAttack(p_217367_);
float f = (float)p_217367_.getAttributeValue(Attributes.ATTACK_DAMAGE);
if (livingentity.hurtServer(p_217366_, damagesource, f)) {
EnchantmentHelper.doPostAttackEffects(p_217366_, livingentity, damagesource);
}
int i = p_217367_.hasEffect(MobEffects.SPEED) ? p_217367_.getEffect(MobEffects.SPEED).getAmplifier() + 1 : 0;
int j = p_217367_.hasEffect(MobEffects.SLOWNESS) ? p_217367_.getEffect(MobEffects.SLOWNESS).getAmplifier() + 1 : 0;
float f1 = 0.25F * (i - j);
float f2 = Mth.clamp(p_217367_.getSpeed() * 1.65F, 0.2F, 3.0F) + f1;
DamageSource damagesource1 = p_217366_.damageSources().mobAttack(p_217367_);
float f3 = livingentity.applyItemBlocking(p_217366_, damagesource1, f);
float f4 = f3 > 0.0F ? 0.5F : 1.0F;
livingentity.knockback(f4 * f2 * this.getKnockbackForce.applyAsDouble(p_217367_), this.ramDirection.x(), this.ramDirection.z());
this.finishRam(p_217366_, p_217367_);
p_217366_.playSound(null, p_217367_, this.getImpactSound.apply(p_217367_), SoundSource.NEUTRAL, 1.0F, 1.0F);
} else if (this.hasRammedHornBreakingBlock(p_217366_, p_217367_)) {
p_217366_.playSound(null, p_217367_, this.getImpactSound.apply(p_217367_), SoundSource.NEUTRAL, 1.0F, 1.0F);
boolean flag = p_217367_.dropHorn();
if (flag) {
p_217366_.playSound(null, p_217367_, this.getHornBreakSound.apply(p_217367_), SoundSource.NEUTRAL, 1.0F, 1.0F);
}
this.finishRam(p_217366_, p_217367_);
} else {
Optional<WalkTarget> optional = brain.getMemory(MemoryModuleType.WALK_TARGET);
Optional<Vec3> optional1 = brain.getMemory(MemoryModuleType.RAM_TARGET);
boolean flag1 = optional.isEmpty() || optional1.isEmpty() || optional.get().getTarget().currentPosition().closerThan(optional1.get(), 0.25);
if (flag1) {
this.finishRam(p_217366_, p_217367_);
}
}
}
private boolean hasRammedHornBreakingBlock(ServerLevel p_217363_, Goat p_217364_) {
Vec3 vec3 = p_217364_.getDeltaMovement().multiply(1.0, 0.0, 1.0).normalize();
BlockPos blockpos = BlockPos.containing(p_217364_.position().add(vec3));
return p_217363_.getBlockState(blockpos).is(BlockTags.SNAPS_GOAT_HORN) || p_217363_.getBlockState(blockpos.above()).is(BlockTags.SNAPS_GOAT_HORN);
}
protected void finishRam(ServerLevel p_217356_, Goat p_217357_) {
p_217356_.broadcastEntityEvent(p_217357_, (byte)59);
p_217357_.getBrain().setMemory(MemoryModuleType.RAM_COOLDOWN_TICKS, this.getTimeBetweenRams.apply(p_217357_).sample(p_217356_.random));
p_217357_.getBrain().eraseMemory(MemoryModuleType.RAM_TARGET);
}
}