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 { private Set 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 figureOutWhatIAmWillingToTrade(Villager villager, Villager other) { ImmutableSet immutableSet = other.getVillagerData().profession().value().requestedItems(); ImmutableSet immutableSet2 = villager.getVillagerData().profession().value().requestedItems(); return (Set)immutableSet.stream().filter(item -> !immutableSet2.contains(item)).collect(Collectors.toSet()); } private static void throwHalfStack(Villager villager, Set 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()); } } }