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

173 lines
8.1 KiB
Java
Raw Normal View History

2025-07-01 06:20:03 +00:00
package net.minecraft.world.entity.ai.behavior;
import com.mojang.datafixers.util.Pair;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap.Entry;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import java.util.function.BiPredicate;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import net.minecraft.core.BlockPos;
import net.minecraft.core.GlobalPos;
import net.minecraft.core.Holder;
import net.minecraft.network.protocol.game.DebugPackets;
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.entity.ai.behavior.declarative.BehaviorBuilder;
import net.minecraft.world.entity.ai.behavior.declarative.MemoryAccessor;
import net.minecraft.world.entity.ai.memory.MemoryModuleType;
import net.minecraft.world.entity.ai.village.poi.PoiManager;
import net.minecraft.world.entity.ai.village.poi.PoiType;
import net.minecraft.world.level.pathfinder.Path;
import org.apache.commons.lang3.mutable.MutableLong;
public class AcquirePoi {
public static final int SCAN_RANGE = 48;
public static BehaviorControl<PathfinderMob> create(
Predicate<Holder<PoiType>> p_260007_,
MemoryModuleType<GlobalPos> p_259129_,
boolean p_259108_,
Optional<Byte> p_260129_,
BiPredicate<ServerLevel, BlockPos> p_376059_
) {
return create(p_260007_, p_259129_, p_259129_, p_259108_, p_260129_, p_376059_);
}
public static BehaviorControl<PathfinderMob> create(
Predicate<Holder<PoiType>> p_259994_, MemoryModuleType<GlobalPos> p_259167_, boolean p_259077_, Optional<Byte> p_259824_
) {
return create(p_259994_, p_259167_, p_259167_, p_259077_, p_259824_, (p_374959_, p_374960_) -> true);
}
public static BehaviorControl<PathfinderMob> create(
Predicate<Holder<PoiType>> p_377768_,
MemoryModuleType<GlobalPos> p_378646_,
MemoryModuleType<GlobalPos> p_375764_,
boolean p_375441_,
Optional<Byte> p_376147_,
BiPredicate<ServerLevel, BlockPos> p_376572_
) {
int i = 5;
int j = 20;
MutableLong mutablelong = new MutableLong(0L);
Long2ObjectMap<AcquirePoi.JitteredLinearRetry> long2objectmap = new Long2ObjectOpenHashMap<>();
OneShot<PathfinderMob> oneshot = BehaviorBuilder.create(
p_374955_ -> p_374955_.group(p_374955_.absent(p_375764_))
.apply(
p_374955_,
p_374967_ -> (p_374945_, p_374946_, p_374947_) -> {
if (p_375441_ && p_374946_.isBaby()) {
return false;
} else if (mutablelong.getValue() == 0L) {
mutablelong.setValue(p_374945_.getGameTime() + p_374945_.random.nextInt(20));
return false;
} else if (p_374945_.getGameTime() < mutablelong.getValue()) {
return false;
} else {
mutablelong.setValue(p_374947_ + 20L + p_374945_.getRandom().nextInt(20));
PoiManager poimanager = p_374945_.getPoiManager();
long2objectmap.long2ObjectEntrySet().removeIf(p_22338_ -> !p_22338_.getValue().isStillValid(p_374947_));
Predicate<BlockPos> predicate = p_258266_ -> {
AcquirePoi.JitteredLinearRetry acquirepoi$jitteredlinearretry = long2objectmap.get(p_258266_.asLong());
if (acquirepoi$jitteredlinearretry == null) {
return true;
} else if (!acquirepoi$jitteredlinearretry.shouldRetry(p_374947_)) {
return false;
} else {
acquirepoi$jitteredlinearretry.markAttempt(p_374947_);
return true;
}
};
Set<Pair<Holder<PoiType>, BlockPos>> set = poimanager.findAllClosestFirstWithType(
p_377768_, predicate, p_374946_.blockPosition(), 48, PoiManager.Occupancy.HAS_SPACE
)
.limit(5L)
.filter(p_374958_ -> p_376572_.test(p_374945_, p_374958_.getSecond()))
.collect(Collectors.toSet());
Path path = findPathToPois(p_374946_, set);
if (path != null && path.canReach()) {
BlockPos blockpos = path.getTarget();
poimanager.getType(blockpos).ifPresent(p_390542_ -> {
poimanager.take(p_377768_, (p_217108_, p_217109_) -> p_217109_.equals(blockpos), blockpos, 1);
p_374967_.set(GlobalPos.of(p_374945_.dimension(), blockpos));
p_376147_.ifPresent(p_147369_ -> p_374945_.broadcastEntityEvent(p_374946_, p_147369_));
long2objectmap.clear();
DebugPackets.sendPoiTicketCountPacket(p_374945_, blockpos);
});
} else {
for (Pair<Holder<PoiType>, BlockPos> pair : set) {
long2objectmap.computeIfAbsent(
pair.getSecond().asLong(), p_264881_ -> new AcquirePoi.JitteredLinearRetry(p_374945_.random, p_374947_)
);
}
}
return true;
}
}
)
);
return p_375764_ == p_378646_
? oneshot
: BehaviorBuilder.create(p_258269_ -> p_258269_.group(p_258269_.absent(p_378646_)).apply(p_258269_, p_258302_ -> oneshot));
}
@Nullable
public static Path findPathToPois(Mob p_217098_, Set<Pair<Holder<PoiType>, BlockPos>> p_217099_) {
if (p_217099_.isEmpty()) {
return null;
} else {
Set<BlockPos> set = new HashSet<>();
int i = 1;
for (Pair<Holder<PoiType>, BlockPos> pair : p_217099_) {
i = Math.max(i, pair.getFirst().value().validRange());
set.add(pair.getSecond());
}
return p_217098_.getNavigation().createPath(set, i);
}
}
static class JitteredLinearRetry {
private static final int MIN_INTERVAL_INCREASE = 40;
private static final int MAX_INTERVAL_INCREASE = 80;
private static final int MAX_RETRY_PATHFINDING_INTERVAL = 400;
private final RandomSource random;
private long previousAttemptTimestamp;
private long nextScheduledAttemptTimestamp;
private int currentDelay;
JitteredLinearRetry(RandomSource p_217111_, long p_217112_) {
this.random = p_217111_;
this.markAttempt(p_217112_);
}
public void markAttempt(long p_22381_) {
this.previousAttemptTimestamp = p_22381_;
int i = this.currentDelay + this.random.nextInt(40) + 40;
this.currentDelay = Math.min(i, 400);
this.nextScheduledAttemptTimestamp = p_22381_ + this.currentDelay;
}
public boolean isStillValid(long p_22383_) {
return p_22383_ - this.previousAttemptTimestamp < 400L;
}
public boolean shouldRetry(long p_22385_) {
return p_22385_ >= this.nextScheduledAttemptTimestamp;
}
@Override
public String toString() {
return "RetryMarker{, previousAttemptAt=" + this.previousAttemptTimestamp + ", nextScheduledAttemptAt=" + this.nextScheduledAttemptTimestamp + ", currentDelay=" + this.currentDelay + "}";
}
}
}