85 lines
3.4 KiB
Java
85 lines
3.4 KiB
Java
package net.minecraft.world.entity.ai.behavior;
|
|
|
|
import java.util.List;
|
|
import java.util.Optional;
|
|
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.world.entity.LivingEntity;
|
|
import net.minecraft.world.entity.PathfinderMob;
|
|
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder;
|
|
import net.minecraft.world.entity.ai.memory.MemoryModuleType;
|
|
import net.minecraft.world.entity.ai.village.poi.PoiType;
|
|
import net.minecraft.world.entity.npc.Villager;
|
|
import net.minecraft.world.entity.npc.VillagerProfession;
|
|
import net.minecraft.world.level.pathfinder.Path;
|
|
|
|
public class YieldJobSite {
|
|
public static BehaviorControl<Villager> create(float speedModifier) {
|
|
return BehaviorBuilder.create(
|
|
instance -> instance.group(
|
|
instance.present(MemoryModuleType.POTENTIAL_JOB_SITE),
|
|
instance.absent(MemoryModuleType.JOB_SITE),
|
|
instance.present(MemoryModuleType.NEAREST_LIVING_ENTITIES),
|
|
instance.registered(MemoryModuleType.WALK_TARGET),
|
|
instance.registered(MemoryModuleType.LOOK_TARGET)
|
|
)
|
|
.apply(
|
|
instance,
|
|
(memoryAccessor, memoryAccessor2, memoryAccessor3, memoryAccessor4, memoryAccessor5) -> (serverLevel, villager, l) -> {
|
|
if (villager.isBaby()) {
|
|
return false;
|
|
} else if (!villager.getVillagerData().profession().is(VillagerProfession.NONE)) {
|
|
return false;
|
|
} else {
|
|
BlockPos blockPos = instance.<GlobalPos>get(memoryAccessor).pos();
|
|
Optional<Holder<PoiType>> optional = serverLevel.getPoiManager().getType(blockPos);
|
|
if (optional.isEmpty()) {
|
|
return true;
|
|
} else {
|
|
instance.<List>get(memoryAccessor3)
|
|
.stream()
|
|
.filter(livingEntity -> livingEntity instanceof Villager && livingEntity != villager)
|
|
.map(livingEntity -> (Villager)livingEntity)
|
|
.filter(LivingEntity::isAlive)
|
|
.filter(villagerx -> nearbyWantsJobsite((Holder<PoiType>)optional.get(), villagerx, blockPos))
|
|
.findFirst()
|
|
.ifPresent(villagerx -> {
|
|
memoryAccessor4.erase();
|
|
memoryAccessor5.erase();
|
|
memoryAccessor.erase();
|
|
if (villagerx.getBrain().getMemory(MemoryModuleType.JOB_SITE).isEmpty()) {
|
|
BehaviorUtils.setWalkAndLookTargetMemories(villagerx, blockPos, speedModifier, 1);
|
|
villagerx.getBrain().setMemory(MemoryModuleType.POTENTIAL_JOB_SITE, GlobalPos.of(serverLevel.dimension(), blockPos));
|
|
DebugPackets.sendPoiTicketCountPacket(serverLevel, blockPos);
|
|
}
|
|
});
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
)
|
|
);
|
|
}
|
|
|
|
private static boolean nearbyWantsJobsite(Holder<PoiType> poi, Villager villager, BlockPos pos) {
|
|
boolean bl = villager.getBrain().getMemory(MemoryModuleType.POTENTIAL_JOB_SITE).isPresent();
|
|
if (bl) {
|
|
return false;
|
|
} else {
|
|
Optional<GlobalPos> optional = villager.getBrain().getMemory(MemoryModuleType.JOB_SITE);
|
|
Holder<VillagerProfession> holder = villager.getVillagerData().profession();
|
|
if (holder.value().heldJobSite().test(poi)) {
|
|
return optional.isEmpty() ? canReachPos(villager, pos, poi.value()) : ((GlobalPos)optional.get()).pos().equals(pos);
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
private static boolean canReachPos(PathfinderMob mob, BlockPos pos, PoiType poi) {
|
|
Path path = mob.getNavigation().createPath(pos, poi.validRange());
|
|
return path != null && path.canReach();
|
|
}
|
|
}
|