108 lines
4.1 KiB
Java
108 lines
4.1 KiB
Java
package net.minecraft.world.entity.ai.behavior;
|
|
|
|
import java.util.Map;
|
|
import java.util.Optional;
|
|
import java.util.function.Function;
|
|
import net.minecraft.Util;
|
|
import net.minecraft.advancements.CriteriaTriggers;
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.server.level.ServerLevel;
|
|
import net.minecraft.server.level.ServerPlayer;
|
|
import net.minecraft.sounds.SoundEvents;
|
|
import net.minecraft.sounds.SoundSource;
|
|
import net.minecraft.world.entity.LivingEntity;
|
|
import net.minecraft.world.entity.ai.memory.MemoryModuleType;
|
|
import net.minecraft.world.entity.ai.memory.MemoryStatus;
|
|
import net.minecraft.world.entity.animal.allay.Allay;
|
|
import net.minecraft.world.entity.animal.allay.AllayAi;
|
|
import net.minecraft.world.entity.npc.InventoryCarrier;
|
|
import net.minecraft.world.item.ItemStack;
|
|
import net.minecraft.world.level.Level;
|
|
import net.minecraft.world.phys.Vec3;
|
|
|
|
public class GoAndGiveItemsToTarget<E extends LivingEntity & InventoryCarrier> extends Behavior<E> {
|
|
private static final int CLOSE_ENOUGH_DISTANCE_TO_TARGET = 3;
|
|
private static final int ITEM_PICKUP_COOLDOWN_AFTER_THROWING = 60;
|
|
private final Function<LivingEntity, Optional<PositionTracker>> targetPositionGetter;
|
|
private final float speedModifier;
|
|
|
|
public GoAndGiveItemsToTarget(Function<LivingEntity, Optional<PositionTracker>> targetPositionGetter, float speedModifier, int duration) {
|
|
super(
|
|
Map.of(
|
|
MemoryModuleType.LOOK_TARGET,
|
|
MemoryStatus.REGISTERED,
|
|
MemoryModuleType.WALK_TARGET,
|
|
MemoryStatus.REGISTERED,
|
|
MemoryModuleType.ITEM_PICKUP_COOLDOWN_TICKS,
|
|
MemoryStatus.REGISTERED
|
|
),
|
|
duration
|
|
);
|
|
this.targetPositionGetter = targetPositionGetter;
|
|
this.speedModifier = speedModifier;
|
|
}
|
|
|
|
@Override
|
|
protected boolean checkExtraStartConditions(ServerLevel level, E owner) {
|
|
return this.canThrowItemToTarget(owner);
|
|
}
|
|
|
|
@Override
|
|
protected boolean canStillUse(ServerLevel level, E entity, long gameTime) {
|
|
return this.canThrowItemToTarget(entity);
|
|
}
|
|
|
|
@Override
|
|
protected void start(ServerLevel level, E entity, long gameTime) {
|
|
((Optional)this.targetPositionGetter.apply(entity))
|
|
.ifPresent(positionTracker -> BehaviorUtils.setWalkAndLookTargetMemories(entity, positionTracker, this.speedModifier, 3));
|
|
}
|
|
|
|
@Override
|
|
protected void tick(ServerLevel level, E owner, long gameTime) {
|
|
Optional<PositionTracker> optional = (Optional<PositionTracker>)this.targetPositionGetter.apply(owner);
|
|
if (!optional.isEmpty()) {
|
|
PositionTracker positionTracker = (PositionTracker)optional.get();
|
|
double d = positionTracker.currentPosition().distanceTo(owner.getEyePosition());
|
|
if (d < 3.0) {
|
|
ItemStack itemStack = owner.getInventory().removeItem(0, 1);
|
|
if (!itemStack.isEmpty()) {
|
|
throwItem(owner, itemStack, getThrowPosition(positionTracker));
|
|
if (owner instanceof Allay allay) {
|
|
AllayAi.getLikedPlayer(allay).ifPresent(serverPlayer -> this.triggerDropItemOnBlock(positionTracker, itemStack, serverPlayer));
|
|
}
|
|
|
|
owner.getBrain().setMemory(MemoryModuleType.ITEM_PICKUP_COOLDOWN_TICKS, 60);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void triggerDropItemOnBlock(PositionTracker positionTracker, ItemStack stack, ServerPlayer player) {
|
|
BlockPos blockPos = positionTracker.currentBlockPosition().below();
|
|
CriteriaTriggers.ALLAY_DROP_ITEM_ON_BLOCK.trigger(player, blockPos, stack);
|
|
}
|
|
|
|
private boolean canThrowItemToTarget(E target) {
|
|
if (target.getInventory().isEmpty()) {
|
|
return false;
|
|
} else {
|
|
Optional<PositionTracker> optional = (Optional<PositionTracker>)this.targetPositionGetter.apply(target);
|
|
return optional.isPresent();
|
|
}
|
|
}
|
|
|
|
private static Vec3 getThrowPosition(PositionTracker positionTracker) {
|
|
return positionTracker.currentPosition().add(0.0, 1.0, 0.0);
|
|
}
|
|
|
|
public static void throwItem(LivingEntity entity, ItemStack stack, Vec3 throwPos) {
|
|
Vec3 vec3 = new Vec3(0.2F, 0.3F, 0.2F);
|
|
BehaviorUtils.throwItem(entity, stack, throwPos, vec3, 0.2F);
|
|
Level level = entity.level();
|
|
if (level.getGameTime() % 7L == 0L && level.random.nextDouble() < 0.9) {
|
|
float f = Util.<Float>getRandom(Allay.THROW_SOUND_PITCHES, level.getRandom());
|
|
level.playSound(null, entity, SoundEvents.ALLAY_THROW, SoundSource.NEUTRAL, 1.0F, f);
|
|
}
|
|
}
|
|
}
|