minecraft-src/net/minecraft/world/entity/ai/behavior/TradeWithVillager.java
2025-07-04 03:45:38 +03:00

113 lines
4 KiB
Java

package net.minecraft.world.entity.ai.behavior;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import java.util.Set;
import java.util.stream.Collectors;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.SimpleContainer;
import net.minecraft.world.entity.EntityType;
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.npc.Villager;
import net.minecraft.world.entity.npc.VillagerProfession;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
public class TradeWithVillager extends Behavior<Villager> {
private Set<Item> trades = ImmutableSet.of();
public TradeWithVillager() {
super(
ImmutableMap.of(
MemoryModuleType.INTERACTION_TARGET, MemoryStatus.VALUE_PRESENT, MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryStatus.VALUE_PRESENT
)
);
}
protected boolean checkExtraStartConditions(ServerLevel level, Villager owner) {
return BehaviorUtils.targetIsValid(owner.getBrain(), MemoryModuleType.INTERACTION_TARGET, EntityType.VILLAGER);
}
protected boolean canStillUse(ServerLevel level, Villager entity, long gameTime) {
return this.checkExtraStartConditions(level, entity);
}
protected void start(ServerLevel level, Villager entity, long gameTime) {
Villager villager = (Villager)entity.getBrain().getMemory(MemoryModuleType.INTERACTION_TARGET).get();
BehaviorUtils.lockGazeAndWalkToEachOther(entity, villager, 0.5F, 2);
this.trades = figureOutWhatIAmWillingToTrade(entity, villager);
}
protected void tick(ServerLevel level, Villager owner, long gameTime) {
Villager villager = (Villager)owner.getBrain().getMemory(MemoryModuleType.INTERACTION_TARGET).get();
if (!(owner.distanceToSqr(villager) > 5.0)) {
BehaviorUtils.lockGazeAndWalkToEachOther(owner, villager, 0.5F, 2);
owner.gossip(level, villager, gameTime);
boolean bl = owner.getVillagerData().profession().is(VillagerProfession.FARMER);
if (owner.hasExcessFood() && (bl || villager.wantsMoreFood())) {
throwHalfStack(owner, Villager.FOOD_POINTS.keySet(), villager);
}
if (bl && owner.getInventory().countItem(Items.WHEAT) > Items.WHEAT.getDefaultMaxStackSize() / 2) {
throwHalfStack(owner, ImmutableSet.of(Items.WHEAT), villager);
}
if (!this.trades.isEmpty() && owner.getInventory().hasAnyOf(this.trades)) {
throwHalfStack(owner, this.trades, villager);
}
}
}
protected void stop(ServerLevel level, Villager entity, long gameTime) {
entity.getBrain().eraseMemory(MemoryModuleType.INTERACTION_TARGET);
}
private static Set<Item> figureOutWhatIAmWillingToTrade(Villager villager, Villager other) {
ImmutableSet<Item> immutableSet = other.getVillagerData().profession().value().requestedItems();
ImmutableSet<Item> immutableSet2 = villager.getVillagerData().profession().value().requestedItems();
return (Set<Item>)immutableSet.stream().filter(item -> !immutableSet2.contains(item)).collect(Collectors.toSet());
}
private static void throwHalfStack(Villager villager, Set<Item> stack, LivingEntity entity) {
SimpleContainer simpleContainer = villager.getInventory();
ItemStack itemStack = ItemStack.EMPTY;
int i = 0;
while (i < simpleContainer.getContainerSize()) {
ItemStack itemStack2;
Item item;
int j;
label28: {
itemStack2 = simpleContainer.getItem(i);
if (!itemStack2.isEmpty()) {
item = itemStack2.getItem();
if (stack.contains(item)) {
if (itemStack2.getCount() > itemStack2.getMaxStackSize() / 2) {
j = itemStack2.getCount() / 2;
break label28;
}
if (itemStack2.getCount() > 24) {
j = itemStack2.getCount() - 24;
break label28;
}
}
}
i++;
continue;
}
itemStack2.shrink(j);
itemStack = new ItemStack(item, j);
break;
}
if (!itemStack.isEmpty()) {
BehaviorUtils.throwItem(villager, itemStack, entity.position());
}
}
}