diff options
Diffstat (limited to 'patch-remap/mache-spigotflower/net/minecraft/world/entity/npc')
5 files changed, 1973 insertions, 0 deletions
diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/npc/AbstractVillager.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/npc/AbstractVillager.java.patch new file mode 100644 index 0000000000..bbff4dd88b --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/npc/AbstractVillager.java.patch @@ -0,0 +1,330 @@ +--- a/net/minecraft/world/entity/npc/AbstractVillager.java ++++ b/net/minecraft/world/entity/npc/AbstractVillager.java +@@ -20,11 +20,11 @@ + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.Pose; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.SlotAccess; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.trading.Merchant; +@@ -34,9 +34,23 @@ + import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.pathfinder.BlockPathTypes; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.inventory.CraftMerchant; ++import org.bukkit.craftbukkit.inventory.CraftMerchantRecipe; ++import org.bukkit.event.entity.VillagerAcquireTradeEvent; ++// CraftBukkit end + +-public abstract class AbstractVillager extends AgeableMob implements InventoryCarrier, Npc, Merchant { ++public abstract class AbstractVillager extends AgeableMob implements InventoryCarrier, NPC, Merchant { + ++ // CraftBukkit start ++ private CraftMerchant craftMerchant; ++ ++ @Override ++ public CraftMerchant getCraftMerchant() { ++ return (craftMerchant == null) ? craftMerchant = new CraftMerchant(this) : craftMerchant; ++ } ++ // CraftBukkit end + private static final EntityDataAccessor<Integer> DATA_UNHAPPY_COUNTER = SynchedEntityData.defineId(AbstractVillager.class, EntityDataSerializers.INT); + public static final int VILLAGER_SLOT_OFFSET = 300; + private static final int VILLAGER_INVENTORY_SIZE = 8; +@@ -44,60 +58,54 @@ + private Player tradingPlayer; + @Nullable + protected MerchantOffers offers; +- private final SimpleContainer inventory = new SimpleContainer(8); ++ private final SimpleContainer inventory = new SimpleContainer(8, (org.bukkit.craftbukkit.entity.CraftAbstractVillager) this.getBukkitEntity()); // CraftBukkit add argument + +- public AbstractVillager(EntityType<? extends AbstractVillager> entitytype, Level level) { +- super(entitytype, level); ++ public AbstractVillager(EntityType<? extends AbstractVillager> entityType, Level level) { ++ super(entityType, level); + this.setPathfindingMalus(BlockPathTypes.DANGER_FIRE, 16.0F); + this.setPathfindingMalus(BlockPathTypes.DAMAGE_FIRE, -1.0F); + } + + @Override +- @Override +- public SpawnGroupData finalizeSpawn(ServerLevelAccessor serverlevelaccessor, DifficultyInstance difficultyinstance, MobSpawnType mobspawntype, @Nullable SpawnGroupData spawngroupdata, @Nullable CompoundTag compoundtag) { +- if (spawngroupdata == null) { +- spawngroupdata = new AgeableMob.AgeableMobGroupData(false); ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ if (spawnData == null) { ++ spawnData = new AgeableMob.AgeableMobGroupData(false); + } + +- return super.finalizeSpawn(serverlevelaccessor, difficultyinstance, mobspawntype, (SpawnGroupData) spawngroupdata, compoundtag); ++ return super.finalizeSpawn(level, difficulty, reason, (GroupDataEntity) spawnData, dataTag); + } + + public int getUnhappyCounter() { + return (Integer) this.entityData.get(AbstractVillager.DATA_UNHAPPY_COUNTER); + } + +- public void setUnhappyCounter(int i) { +- this.entityData.set(AbstractVillager.DATA_UNHAPPY_COUNTER, i); ++ public void setUnhappyCounter(int unhappyCounter) { ++ this.entityData.set(AbstractVillager.DATA_UNHAPPY_COUNTER, unhappyCounter); + } + + @Override +- @Override + public int getVillagerXp() { + return 0; + } + + @Override +- @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions entitydimensions) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return this.isBaby() ? 0.81F : 1.62F; + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(AbstractVillager.DATA_UNHAPPY_COUNTER, 0); + } + + @Override +- @Override + public void setTradingPlayer(@Nullable Player player) { + this.tradingPlayer = player; + } + + @Nullable + @Override +- @Override + public Player getTradingPlayer() { + return this.tradingPlayer; + } +@@ -107,7 +115,6 @@ + } + + @Override +- @Override + public MerchantOffers getOffers() { + if (this.offers == null) { + this.offers = new MerchantOffers(); +@@ -118,21 +125,18 @@ + } + + @Override +- @Override +- public void overrideOffers(@Nullable MerchantOffers merchantoffers) {} ++ public void overrideOffers(@Nullable MerchantOffers offers) {} + + @Override +- @Override +- public void overrideXp(int i) {} ++ public void overrideXp(int xp) {} + + @Override +- @Override +- public void notifyTrade(MerchantOffer merchantoffer) { +- merchantoffer.increaseUses(); ++ public void notifyTrade(MerchantOffer offer) { ++ offer.increaseUses(); + this.ambientSoundTime = -this.getAmbientSoundInterval(); +- this.rewardTradeXp(merchantoffer); ++ this.rewardTradeXp(offer); + if (this.tradingPlayer instanceof ServerPlayer) { +- CriteriaTriggers.TRADE.trigger((ServerPlayer) this.tradingPlayer, this, merchantoffer.getResult()); ++ CriteriaTriggers.TRADE.trigger((ServerPlayer) this.tradingPlayer, this, offer.getResult()); + } + + } +@@ -140,29 +144,26 @@ + protected abstract void rewardTradeXp(MerchantOffer offer); + + @Override +- @Override + public boolean showProgressBar() { + return true; + } + + @Override +- @Override +- public void notifyTradeUpdated(ItemStack itemstack) { ++ public void notifyTradeUpdated(ItemStack stack) { + if (!this.level().isClientSide && this.ambientSoundTime > -this.getAmbientSoundInterval() + 20) { + this.ambientSoundTime = -this.getAmbientSoundInterval(); +- this.playSound(this.getTradeUpdatedSound(!itemstack.isEmpty()), this.getSoundVolume(), this.getVoicePitch()); ++ this.playSound(this.getTradeUpdatedSound(!stack.isEmpty()), this.getSoundVolume(), this.getVoicePitch()); + } + + } + + @Override +- @Override + public SoundEvent getNotifyTradeSound() { + return SoundEvents.VILLAGER_YES; + } + +- protected SoundEvent getTradeUpdatedSound(boolean flag) { +- return flag ? SoundEvents.VILLAGER_YES : SoundEvents.VILLAGER_NO; ++ protected SoundEvent getTradeUpdatedSound(boolean isYesSound) { ++ return isYesSound ? SoundEvents.VILLAGER_YES : SoundEvents.VILLAGER_NO; + } + + public void playCelebrateSound() { +@@ -170,35 +171,32 @@ + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- MerchantOffers merchantoffers = this.getOffers(); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ MerchantOffers merchantrecipelist = this.getOffers(); + +- if (!merchantoffers.isEmpty()) { +- compoundtag.put("Offers", merchantoffers.createTag()); ++ if (!merchantrecipelist.isEmpty()) { ++ compound.put("Offers", merchantrecipelist.createTag()); + } + +- this.writeInventoryToTag(compoundtag); ++ this.writeInventoryToTag(compound); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- if (compoundtag.contains("Offers", 10)) { +- this.offers = new MerchantOffers(compoundtag.getCompound("Offers")); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ if (compound.contains("Offers", 10)) { ++ this.offers = new MerchantOffers(compound.getCompound("Offers")); + } + +- this.readInventoryFromTag(compoundtag); ++ this.readInventoryFromTag(compound); + } + + @Nullable + @Override +- @Override +- public Entity changeDimension(ServerLevel serverlevel) { ++ public Entity changeDimension(ServerLevel server) { + this.stopTrading(); +- return super.changeDimension(serverlevel); ++ return super.changeDimension(server); + } + + protected void stopTrading() { +@@ -206,54 +204,59 @@ + } + + @Override +- @Override +- public void die(DamageSource damagesource) { +- super.die(damagesource); ++ public void die(DamageSource cause) { ++ super.die(cause); + this.stopTrading(); + } + +- protected void addParticlesAroundSelf(ParticleOptions particleoptions) { ++ protected void addParticlesAroundSelf(ParticleOptions particleOption) { + for (int i = 0; i < 5; ++i) { + double d0 = this.random.nextGaussian() * 0.02D; + double d1 = this.random.nextGaussian() * 0.02D; + double d2 = this.random.nextGaussian() * 0.02D; + +- this.level().addParticle(particleoptions, this.getRandomX(1.0D), this.getRandomY() + 1.0D, this.getRandomZ(1.0D), d0, d1, d2); ++ this.level().addParticle(particleOption, this.getRandomX(1.0D), this.getRandomY() + 1.0D, this.getRandomZ(1.0D), d0, d1, d2); + } + + } + + @Override +- @Override + public boolean canBeLeashed(Player player) { + return false; + } + + @Override +- @Override + public SimpleContainer getInventory() { + return this.inventory; + } + + @Override +- @Override +- public SlotAccess getSlot(int i) { +- int j = i - 300; ++ public SlotAccess getSlot(int slot) { ++ int j = slot - 300; + +- return j >= 0 && j < this.inventory.getContainerSize() ? SlotAccess.forContainer(this.inventory, j) : super.getSlot(i); ++ return j >= 0 && j < this.inventory.getContainerSize() ? SlotAccess.forContainer(this.inventory, j) : super.getSlot(slot); + } + + protected abstract void updateTrades(); + +- protected void addOffersFromItemListings(MerchantOffers merchantoffers, VillagerTrades.ItemListing[] avillagertrades_itemlisting, int i) { +- ArrayList<VillagerTrades.ItemListing> arraylist = Lists.newArrayList(avillagertrades_itemlisting); ++ protected void addOffersFromItemListings(MerchantOffers givenMerchantOffers, VillagerTrades.ItemListing[] newTrades, int maxNumbers) { ++ ArrayList<VillagerTrades.ItemListing> arraylist = Lists.newArrayList(newTrades); + int j = 0; + +- while (j < i && !arraylist.isEmpty()) { +- MerchantOffer merchantoffer = ((VillagerTrades.ItemListing) arraylist.remove(this.random.nextInt(arraylist.size()))).getOffer(this, this.random); ++ while (j < maxNumbers && !arraylist.isEmpty()) { ++ MerchantOffer merchantrecipe = ((VillagerTrades.ItemListing) arraylist.remove(this.random.nextInt(arraylist.size()))).getOffer(this, this.random); + +- if (merchantoffer != null) { +- merchantoffers.add(merchantoffer); ++ if (merchantrecipe != null) { ++ // CraftBukkit start ++ VillagerAcquireTradeEvent event = new VillagerAcquireTradeEvent((org.bukkit.entity.AbstractVillager) getBukkitEntity(), merchantrecipe.asBukkit()); ++ // Suppress during worldgen ++ if (this.valid) { ++ Bukkit.getPluginManager().callEvent(event); ++ } ++ if (!event.isCancelled()) { ++ givenMerchantOffers.add(CraftMerchantRecipe.fromBukkit(event.getRecipe()).toMinecraft()); ++ } ++ // CraftBukkit end + ++j; + } + } +@@ -261,16 +264,14 @@ + } + + @Override +- @Override +- public Vec3 getRopeHoldPosition(float f) { +- float f1 = Mth.lerp(f, this.yBodyRotO, this.yBodyRot) * 0.017453292F; +- Vec3 vec3 = new Vec3(0.0D, this.getBoundingBox().getYsize() - 1.0D, 0.2D); ++ public Vec3 getRopeHoldPosition(float partialTicks) { ++ float f1 = Mth.lerp(partialTicks, this.yBodyRotO, this.yBodyRot) * 0.017453292F; ++ Vec3 vec3d = new Vec3(0.0D, this.getBoundingBox().getYsize() - 1.0D, 0.2D); + +- return this.getPosition(f).add(vec3.yRot(-f1)); ++ return this.getPosition(partialTicks).add(vec3d.yRot(-f1)); + } + + @Override +- @Override + public boolean isClientSide() { + return this.level().isClientSide; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/npc/InventoryCarrier.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/npc/InventoryCarrier.java.patch new file mode 100644 index 0000000000..6a380696ae --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/npc/InventoryCarrier.java.patch @@ -0,0 +1,62 @@ +--- a/net/minecraft/world/entity/npc/InventoryCarrier.java ++++ b/net/minecraft/world/entity/npc/InventoryCarrier.java +@@ -12,24 +12,31 @@ + + SimpleContainer getInventory(); + +- static void pickUpItem(Mob mob, InventoryCarrier inventorycarrier, ItemEntity itementity) { +- ItemStack itemstack = itementity.getItem(); ++ static void pickUpItem(Mob mob, InventoryCarrier carrier, ItemEntity itemEntity) { ++ ItemStack itemstack = itemEntity.getItem(); + + if (mob.wantsToPickUp(itemstack)) { +- SimpleContainer simplecontainer = inventorycarrier.getInventory(); +- boolean flag = simplecontainer.canAddItem(itemstack); ++ SimpleContainer inventorysubcontainer = carrier.getInventory(); ++ boolean flag = inventorysubcontainer.canAddItem(itemstack); + + if (!flag) { + return; + } + +- mob.onItemPickup(itementity); ++ // CraftBukkit start ++ ItemStack remaining = new SimpleContainer(inventorysubcontainer).addItem(itemstack); ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(mob, itemEntity, remaining.getCount(), false).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ ++ mob.onItemPickup(itemEntity); + int i = itemstack.getCount(); +- ItemStack itemstack1 = simplecontainer.addItem(itemstack); ++ ItemStack itemstack1 = inventorysubcontainer.addItem(itemstack); + +- mob.take(itementity, i - itemstack1.getCount()); ++ mob.take(itemEntity, i - itemstack1.getCount()); + if (itemstack1.isEmpty()) { +- itementity.discard(); ++ itemEntity.discard(); + } else { + itemstack.setCount(itemstack1.getCount()); + } +@@ -37,14 +44,14 @@ + + } + +- default void readInventoryFromTag(CompoundTag compoundtag) { +- if (compoundtag.contains("Inventory", 9)) { +- this.getInventory().fromTag(compoundtag.getList("Inventory", 10)); ++ default void readInventoryFromTag(CompoundTag tag) { ++ if (tag.contains("Inventory", 9)) { ++ this.getInventory().fromTag(tag.getList("Inventory", 10)); + } + + } + +- default void writeInventoryToTag(CompoundTag compoundtag) { +- compoundtag.put("Inventory", this.getInventory().createTag()); ++ default void writeInventoryToTag(CompoundTag tag) { ++ tag.put("Inventory", this.getInventory().createTag()); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/npc/Villager.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/npc/Villager.java.patch new file mode 100644 index 0000000000..4a2f676dd8 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/npc/Villager.java.patch @@ -0,0 +1,1032 @@ +--- a/net/minecraft/world/entity/npc/Villager.java ++++ b/net/minecraft/world/entity/npc/Villager.java +@@ -42,7 +42,7 @@ + import net.minecraft.util.SpawnUtil; + import net.minecraft.world.Difficulty; + import net.minecraft.world.DifficultyInstance; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.SimpleContainer; + import net.minecraft.world.damagesource.DamageSource; +@@ -51,13 +51,13 @@ + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.ExperienceOrb; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LightningBolt; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; + import net.minecraft.world.entity.ReputationEventHandler; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.Brain; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; +@@ -92,6 +92,13 @@ + import net.minecraft.world.phys.AABB; + import org.slf4j.Logger; + ++// CraftBukkit start ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTransformEvent; ++import org.bukkit.event.entity.VillagerReplenishTradeEvent; ++// CraftBukkit end ++ + public class Villager extends AbstractVillager implements ReputationEventHandler, VillagerDataHolder { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -125,85 +132,81 @@ + private boolean assignProfessionWhenSpawned; + private static final ImmutableList<MemoryModuleType<?>> MEMORY_TYPES = ImmutableList.of(MemoryModuleType.HOME, MemoryModuleType.JOB_SITE, MemoryModuleType.POTENTIAL_JOB_SITE, MemoryModuleType.MEETING_POINT, MemoryModuleType.NEAREST_LIVING_ENTITIES, MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryModuleType.VISIBLE_VILLAGER_BABIES, MemoryModuleType.NEAREST_PLAYERS, MemoryModuleType.NEAREST_VISIBLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, MemoryModuleType.ITEM_PICKUP_COOLDOWN_TICKS, new MemoryModuleType[]{MemoryModuleType.WALK_TARGET, MemoryModuleType.LOOK_TARGET, MemoryModuleType.INTERACTION_TARGET, MemoryModuleType.BREED_TARGET, MemoryModuleType.PATH, MemoryModuleType.DOORS_TO_CLOSE, MemoryModuleType.NEAREST_BED, MemoryModuleType.HURT_BY, MemoryModuleType.HURT_BY_ENTITY, MemoryModuleType.NEAREST_HOSTILE, MemoryModuleType.SECONDARY_JOB_SITE, MemoryModuleType.HIDING_PLACE, MemoryModuleType.HEARD_BELL_TIME, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryModuleType.LAST_SLEPT, MemoryModuleType.LAST_WOKEN, MemoryModuleType.LAST_WORKED_AT_POI, MemoryModuleType.GOLEM_DETECTED_RECENTLY}); + private static final ImmutableList<SensorType<? extends Sensor<? super Villager>>> SENSOR_TYPES = ImmutableList.of(SensorType.NEAREST_LIVING_ENTITIES, SensorType.NEAREST_PLAYERS, SensorType.NEAREST_ITEMS, SensorType.NEAREST_BED, SensorType.HURT_BY, SensorType.VILLAGER_HOSTILES, SensorType.VILLAGER_BABIES, SensorType.SECONDARY_POIS, SensorType.GOLEM_DETECTED); +- public static final Map<MemoryModuleType<GlobalPos>, BiPredicate<Villager, Holder<PoiType>>> POI_MEMORIES = ImmutableMap.of(MemoryModuleType.HOME, (villager, holder) -> { ++ public static final Map<MemoryModuleType<GlobalPos>, BiPredicate<Villager, Holder<PoiType>>> POI_MEMORIES = ImmutableMap.of(MemoryModuleType.HOME, (entityvillager, holder) -> { + return holder.is(PoiTypes.HOME); +- }, MemoryModuleType.JOB_SITE, (villager, holder) -> { +- return villager.getVillagerData().getProfession().heldJobSite().test(holder); +- }, MemoryModuleType.POTENTIAL_JOB_SITE, (villager, holder) -> { ++ }, MemoryModuleType.JOB_SITE, (entityvillager, holder) -> { ++ return entityvillager.getVillagerData().getProfession().heldJobSite().test(holder); ++ }, MemoryModuleType.POTENTIAL_JOB_SITE, (entityvillager, holder) -> { + return VillagerProfession.ALL_ACQUIRABLE_JOBS.test(holder); +- }, MemoryModuleType.MEETING_POINT, (villager, holder) -> { ++ }, MemoryModuleType.MEETING_POINT, (entityvillager, holder) -> { + return holder.is(PoiTypes.MEETING); + }); + +- public Villager(EntityType<? extends Villager> entitytype, Level level) { +- this(entitytype, level, VillagerType.PLAINS); ++ public Villager(EntityType<? extends Villager> entityType, Level level) { ++ this(entityType, level, VillagerType.PLAINS); + } + +- public Villager(EntityType<? extends Villager> entitytype, Level level, VillagerType villagertype) { +- super(entitytype, level); ++ public Villager(EntityType<? extends Villager> entityType, Level level, VillagerType villagerType) { ++ super(entityType, level); + this.gossips = new GossipContainer(); + ((GroundPathNavigation) this.getNavigation()).setCanOpenDoors(true); + this.getNavigation().setCanFloat(true); + this.setCanPickUpLoot(true); +- this.setVillagerData(this.getVillagerData().setType(villagertype).setProfession(VillagerProfession.NONE)); ++ this.setVillagerData(this.getVillagerData().setType(villagerType).setProfession(VillagerProfession.NONE)); + } + + @Override +- @Override + public Brain<Villager> getBrain() { +- return super.getBrain(); ++ return (Brain<Villager>) super.getBrain(); // CraftBukkit - decompile error + } + + @Override +- @Override + protected Brain.Provider<Villager> brainProvider() { + return Brain.provider(Villager.MEMORY_TYPES, Villager.SENSOR_TYPES); + } + + @Override +- @Override + protected Brain<?> makeBrain(Dynamic<?> dynamic) { +- Brain<Villager> brain = this.brainProvider().makeBrain(dynamic); ++ Brain<Villager> behaviorcontroller = this.brainProvider().makeBrain(dynamic); + +- this.registerBrainGoals(brain); +- return brain; ++ this.registerBrainGoals(behaviorcontroller); ++ return behaviorcontroller; + } + +- public void refreshBrain(ServerLevel serverlevel) { +- Brain<Villager> brain = this.getBrain(); ++ public void refreshBrain(ServerLevel serverLevel) { ++ Brain<Villager> behaviorcontroller = this.getBrain(); + +- brain.stopAll(serverlevel, this); +- this.brain = brain.copyWithoutBehaviors(); ++ behaviorcontroller.stopAll(serverLevel, this); ++ this.brain = behaviorcontroller.copyWithoutBehaviors(); + this.registerBrainGoals(this.getBrain()); + } + +- private void registerBrainGoals(Brain<Villager> brain) { ++ private void registerBrainGoals(Brain<Villager> villagerBrain) { + VillagerProfession villagerprofession = this.getVillagerData().getProfession(); + + if (this.isBaby()) { +- brain.setSchedule(Schedule.VILLAGER_BABY); +- brain.addActivity(Activity.PLAY, VillagerGoalPackages.getPlayPackage(0.5F)); ++ villagerBrain.setSchedule(Schedule.VILLAGER_BABY); ++ villagerBrain.addActivity(Activity.PLAY, VillagerGoalPackages.getPlayPackage(0.5F)); + } else { +- brain.setSchedule(Schedule.VILLAGER_DEFAULT); +- brain.addActivityWithConditions(Activity.WORK, VillagerGoalPackages.getWorkPackage(villagerprofession, 0.5F), ImmutableSet.of(Pair.of(MemoryModuleType.JOB_SITE, MemoryStatus.VALUE_PRESENT))); ++ villagerBrain.setSchedule(Schedule.VILLAGER_DEFAULT); ++ villagerBrain.addActivityWithConditions(Activity.WORK, VillagerGoalPackages.getWorkPackage(villagerprofession, 0.5F), ImmutableSet.of(Pair.of(MemoryModuleType.JOB_SITE, MemoryStatus.VALUE_PRESENT))); + } + +- brain.addActivity(Activity.CORE, VillagerGoalPackages.getCorePackage(villagerprofession, 0.5F)); +- brain.addActivityWithConditions(Activity.MEET, VillagerGoalPackages.getMeetPackage(villagerprofession, 0.5F), ImmutableSet.of(Pair.of(MemoryModuleType.MEETING_POINT, MemoryStatus.VALUE_PRESENT))); +- brain.addActivity(Activity.REST, VillagerGoalPackages.getRestPackage(villagerprofession, 0.5F)); +- brain.addActivity(Activity.IDLE, VillagerGoalPackages.getIdlePackage(villagerprofession, 0.5F)); +- brain.addActivity(Activity.PANIC, VillagerGoalPackages.getPanicPackage(villagerprofession, 0.5F)); +- brain.addActivity(Activity.PRE_RAID, VillagerGoalPackages.getPreRaidPackage(villagerprofession, 0.5F)); +- brain.addActivity(Activity.RAID, VillagerGoalPackages.getRaidPackage(villagerprofession, 0.5F)); +- brain.addActivity(Activity.HIDE, VillagerGoalPackages.getHidePackage(villagerprofession, 0.5F)); +- brain.setCoreActivities(ImmutableSet.of(Activity.CORE)); +- brain.setDefaultActivity(Activity.IDLE); +- brain.setActiveActivityIfPossible(Activity.IDLE); +- brain.updateActivityFromSchedule(this.level().getDayTime(), this.level().getGameTime()); ++ villagerBrain.addActivity(Activity.CORE, VillagerGoalPackages.getCorePackage(villagerprofession, 0.5F)); ++ villagerBrain.addActivityWithConditions(Activity.MEET, VillagerGoalPackages.getMeetPackage(villagerprofession, 0.5F), ImmutableSet.of(Pair.of(MemoryModuleType.MEETING_POINT, MemoryStatus.VALUE_PRESENT))); ++ villagerBrain.addActivity(Activity.REST, VillagerGoalPackages.getRestPackage(villagerprofession, 0.5F)); ++ villagerBrain.addActivity(Activity.IDLE, VillagerGoalPackages.getIdlePackage(villagerprofession, 0.5F)); ++ villagerBrain.addActivity(Activity.PANIC, VillagerGoalPackages.getPanicPackage(villagerprofession, 0.5F)); ++ villagerBrain.addActivity(Activity.PRE_RAID, VillagerGoalPackages.getPreRaidPackage(villagerprofession, 0.5F)); ++ villagerBrain.addActivity(Activity.RAID, VillagerGoalPackages.getRaidPackage(villagerprofession, 0.5F)); ++ villagerBrain.addActivity(Activity.HIDE, VillagerGoalPackages.getHidePackage(villagerprofession, 0.5F)); ++ villagerBrain.setCoreActivities(ImmutableSet.of(Activity.CORE)); ++ villagerBrain.setDefaultActivity(Activity.IDLE); ++ villagerBrain.setActiveActivityIfPossible(Activity.IDLE); ++ villagerBrain.updateActivityFromSchedule(this.level().getDayTime(), this.level().getGameTime()); + } + + @Override +- @Override + protected void ageBoundaryReached() { + super.ageBoundaryReached(); + if (this.level() instanceof ServerLevel) { +@@ -221,7 +224,6 @@ + } + + @Override +- @Override + protected void customServerAiStep() { + this.level().getProfiler().push("villagerBrain"); + this.getBrain().tick((ServerLevel) this.level(), this); +@@ -238,7 +240,7 @@ + this.increaseProfessionLevelOnUpdate = false; + } + +- this.addEffect(new MobEffectInstance(MobEffects.REGENERATION, 200, 0)); ++ this.addEffect(new MobEffectInstance(MobEffects.REGENERATION, 200, 0), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.VILLAGER_TRADE); // CraftBukkit + } + } + +@@ -264,7 +266,6 @@ + } + + @Override +- @Override + public void tick() { + super.tick(); + if (this.getUnhappyCounter() > 0) { +@@ -275,9 +276,8 @@ + } + + @Override +- @Override +- public InteractionResult mobInteract(Player player, InteractionHand interactionhand) { +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); + + if (!itemstack.is(Items.VILLAGER_SPAWN_EGG) && this.isAlive() && !this.isTrading() && !this.isSleeping()) { + if (this.isBaby()) { +@@ -286,7 +286,7 @@ + } else { + boolean flag = this.getOffers().isEmpty(); + +- if (interactionhand == InteractionHand.MAIN_HAND) { ++ if (hand == EnumHand.MAIN_HAND) { + if (flag && !this.level().isClientSide) { + this.setUnhappy(); + } +@@ -305,11 +305,11 @@ + } + } + } else { +- return super.mobInteract(player, interactionhand); ++ return super.mobInteract(player, hand); + } + } + +- private void setUnhappy() { ++ public void setUnhappy() { + this.setUnhappyCounter(40); + if (!this.level().isClientSide()) { + this.playSound(SoundEvents.VILLAGER_NO, this.getSoundVolume(), this.getVoicePitch()); +@@ -324,7 +324,6 @@ + } + + @Override +- @Override + public void setTradingPlayer(@Nullable Player player) { + boolean flag = this.getTradingPlayer() != null && player == null; + +@@ -336,7 +335,6 @@ + } + + @Override +- @Override + protected void stopTrading() { + super.stopTrading(); + this.resetSpecialPrices(); +@@ -346,21 +344,19 @@ + Iterator iterator = this.getOffers().iterator(); + + while (iterator.hasNext()) { +- MerchantOffer merchantoffer = (MerchantOffer) iterator.next(); ++ MerchantOffer merchantrecipe = (MerchantOffer) iterator.next(); + +- merchantoffer.resetSpecialPriceDiff(); ++ merchantrecipe.resetSpecialPriceDiff(); + } + + } + + @Override +- @Override + public boolean canRestock() { + return true; + } + + @Override +- @Override + public boolean isClientSide() { + return this.level().isClientSide; + } +@@ -370,9 +366,15 @@ + Iterator iterator = this.getOffers().iterator(); + + while (iterator.hasNext()) { +- MerchantOffer merchantoffer = (MerchantOffer) iterator.next(); ++ MerchantOffer merchantrecipe = (MerchantOffer) iterator.next(); + +- merchantoffer.resetUses(); ++ // CraftBukkit start ++ VillagerReplenishTradeEvent event = new VillagerReplenishTradeEvent((org.bukkit.entity.Villager) this.getBukkitEntity(), merchantrecipe.asBukkit()); ++ Bukkit.getPluginManager().callEvent(event); ++ if (!event.isCancelled()) { ++ merchantrecipe.resetUses(); ++ } ++ // CraftBukkit end + } + + this.resendOffersToTradingPlayer(); +@@ -381,11 +383,11 @@ + } + + private void resendOffersToTradingPlayer() { +- MerchantOffers merchantoffers = this.getOffers(); +- Player player = this.getTradingPlayer(); ++ MerchantOffers merchantrecipelist = this.getOffers(); ++ Player entityhuman = this.getTradingPlayer(); + +- if (player != null && !merchantoffers.isEmpty()) { +- player.sendMerchantOffers(player.containerMenu.containerId, merchantoffers, this.getVillagerData().getLevel(), this.getVillagerXp(), this.showProgressBar(), this.canRestock()); ++ if (entityhuman != null && !merchantrecipelist.isEmpty()) { ++ entityhuman.sendMerchantOffers(entityhuman.containerMenu.containerId, merchantrecipelist, this.getVillagerData().getLevel(), this.getVillagerXp(), this.showProgressBar(), this.canRestock()); + } + + } +@@ -393,15 +395,15 @@ + private boolean needsToRestock() { + Iterator iterator = this.getOffers().iterator(); + +- MerchantOffer merchantoffer; ++ MerchantOffer merchantrecipe; + + do { + if (!iterator.hasNext()) { + return false; + } + +- merchantoffer = (MerchantOffer) iterator.next(); +- } while (!merchantoffer.needsRestock()); ++ merchantrecipe = (MerchantOffer) iterator.next(); ++ } while (!merchantrecipe.needsRestock()); + + return true; + } +@@ -439,9 +441,15 @@ + Iterator iterator = this.getOffers().iterator(); + + while (iterator.hasNext()) { +- MerchantOffer merchantoffer = (MerchantOffer) iterator.next(); ++ MerchantOffer merchantrecipe = (MerchantOffer) iterator.next(); + +- merchantoffer.resetUses(); ++ // CraftBukkit start ++ VillagerReplenishTradeEvent event = new VillagerReplenishTradeEvent((org.bukkit.entity.Villager) this.getBukkitEntity(), merchantrecipe.asBukkit()); ++ Bukkit.getPluginManager().callEvent(event); ++ if (!event.isCancelled()) { ++ merchantrecipe.resetUses(); ++ } ++ // CraftBukkit end + } + } + +@@ -456,9 +464,9 @@ + Iterator iterator = this.getOffers().iterator(); + + while (iterator.hasNext()) { +- MerchantOffer merchantoffer = (MerchantOffer) iterator.next(); ++ MerchantOffer merchantrecipe = (MerchantOffer) iterator.next(); + +- merchantoffer.updateDemand(); ++ merchantrecipe.updateDemand(); + } + + } +@@ -470,157 +478,147 @@ + Iterator iterator = this.getOffers().iterator(); + + while (iterator.hasNext()) { +- MerchantOffer merchantoffer = (MerchantOffer) iterator.next(); ++ MerchantOffer merchantrecipe = (MerchantOffer) iterator.next(); + +- merchantoffer.addToSpecialPriceDiff(-Mth.floor((float) i * merchantoffer.getPriceMultiplier())); ++ merchantrecipe.addToSpecialPriceDiff(-Mth.floor((float) i * merchantrecipe.getPriceMultiplier())); + } + } + + if (player.hasEffect(MobEffects.HERO_OF_THE_VILLAGE)) { +- MobEffectInstance mobeffectinstance = player.getEffect(MobEffects.HERO_OF_THE_VILLAGE); +- int j = mobeffectinstance.getAmplifier(); ++ MobEffectInstance mobeffect = player.getEffect(MobEffects.HERO_OF_THE_VILLAGE); ++ int j = mobeffect.getAmplifier(); + Iterator iterator1 = this.getOffers().iterator(); + + while (iterator1.hasNext()) { +- MerchantOffer merchantoffer1 = (MerchantOffer) iterator1.next(); ++ MerchantOffer merchantrecipe1 = (MerchantOffer) iterator1.next(); + double d0 = 0.3D + 0.0625D * (double) j; +- int k = (int) Math.floor(d0 * (double) merchantoffer1.getBaseCostA().getCount()); ++ int k = (int) Math.floor(d0 * (double) merchantrecipe1.getBaseCostA().getCount()); + +- merchantoffer1.addToSpecialPriceDiff(-Math.max(k, 1)); ++ merchantrecipe1.addToSpecialPriceDiff(-Math.max(k, 1)); + } + } + + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(Villager.DATA_VILLAGER_DATA, new VillagerData(VillagerType.PLAINS, VillagerProfession.NONE, 1)); + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- DataResult dataresult = VillagerData.CODEC.encodeStart(NbtOps.INSTANCE, this.getVillagerData()); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ DataResult<Tag> dataresult = VillagerData.CODEC.encodeStart(NbtOps.INSTANCE, this.getVillagerData()); // CraftBukkit - decompile error + Logger logger = Villager.LOGGER; + + Objects.requireNonNull(logger); +- dataresult.resultOrPartial(logger::error).ifPresent((tag) -> { +- compoundtag.put("VillagerData", tag); ++ dataresult.resultOrPartial(logger::error).ifPresent((nbtbase) -> { ++ compound.put("VillagerData", nbtbase); + }); +- compoundtag.putByte("FoodLevel", (byte) this.foodLevel); +- compoundtag.put("Gossips", (Tag) this.gossips.store(NbtOps.INSTANCE)); +- compoundtag.putInt("Xp", this.villagerXp); +- compoundtag.putLong("LastRestock", this.lastRestockGameTime); +- compoundtag.putLong("LastGossipDecay", this.lastGossipDecayTime); +- compoundtag.putInt("RestocksToday", this.numberOfRestocksToday); ++ compound.putByte("FoodLevel", (byte) this.foodLevel); ++ compound.put("Gossips", (Tag) this.gossips.store(NbtOps.INSTANCE)); ++ compound.putInt("Xp", this.villagerXp); ++ compound.putLong("LastRestock", this.lastRestockGameTime); ++ compound.putLong("LastGossipDecay", this.lastGossipDecayTime); ++ compound.putInt("RestocksToday", this.numberOfRestocksToday); + if (this.assignProfessionWhenSpawned) { +- compoundtag.putBoolean("AssignProfessionWhenSpawned", true); ++ compound.putBoolean("AssignProfessionWhenSpawned", true); + } + + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- if (compoundtag.contains("VillagerData", 10)) { +- DataResult<VillagerData> dataresult = VillagerData.CODEC.parse(new Dynamic(NbtOps.INSTANCE, compoundtag.get("VillagerData"))); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ if (compound.contains("VillagerData", 10)) { ++ DataResult<VillagerData> dataresult = VillagerData.CODEC.parse(new Dynamic(NbtOps.INSTANCE, compound.get("VillagerData"))); + Logger logger = Villager.LOGGER; + + Objects.requireNonNull(logger); + dataresult.resultOrPartial(logger::error).ifPresent(this::setVillagerData); + } + +- if (compoundtag.contains("Offers", 10)) { +- this.offers = new MerchantOffers(compoundtag.getCompound("Offers")); ++ if (compound.contains("Offers", 10)) { ++ this.offers = new MerchantOffers(compound.getCompound("Offers")); + } + +- if (compoundtag.contains("FoodLevel", 1)) { +- this.foodLevel = compoundtag.getByte("FoodLevel"); ++ if (compound.contains("FoodLevel", 1)) { ++ this.foodLevel = compound.getByte("FoodLevel"); + } + +- ListTag listtag = compoundtag.getList("Gossips", 10); ++ ListTag nbttaglist = compound.getList("Gossips", 10); + +- this.gossips.update(new Dynamic(NbtOps.INSTANCE, listtag)); +- if (compoundtag.contains("Xp", 3)) { +- this.villagerXp = compoundtag.getInt("Xp"); ++ this.gossips.update(new Dynamic(NbtOps.INSTANCE, nbttaglist)); ++ if (compound.contains("Xp", 3)) { ++ this.villagerXp = compound.getInt("Xp"); + } + +- this.lastRestockGameTime = compoundtag.getLong("LastRestock"); +- this.lastGossipDecayTime = compoundtag.getLong("LastGossipDecay"); ++ this.lastRestockGameTime = compound.getLong("LastRestock"); ++ this.lastGossipDecayTime = compound.getLong("LastGossipDecay"); + this.setCanPickUpLoot(true); + if (this.level() instanceof ServerLevel) { + this.refreshBrain((ServerLevel) this.level()); + } + +- this.numberOfRestocksToday = compoundtag.getInt("RestocksToday"); +- if (compoundtag.contains("AssignProfessionWhenSpawned")) { +- this.assignProfessionWhenSpawned = compoundtag.getBoolean("AssignProfessionWhenSpawned"); ++ this.numberOfRestocksToday = compound.getInt("RestocksToday"); ++ if (compound.contains("AssignProfessionWhenSpawned")) { ++ this.assignProfessionWhenSpawned = compound.getBoolean("AssignProfessionWhenSpawned"); + } + + } + + @Override +- @Override +- public boolean removeWhenFarAway(double d0) { ++ public boolean removeWhenFarAway(double distanceToClosestPlayer) { + return false; + } + + @Nullable + @Override +- @Override + protected SoundEvent getAmbientSound() { + return this.isSleeping() ? null : (this.isTrading() ? SoundEvents.VILLAGER_TRADE : SoundEvents.VILLAGER_AMBIENT); + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.VILLAGER_HURT; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.VILLAGER_DEATH; + } + + public void playWorkSound() { +- SoundEvent soundevent = this.getVillagerData().getProfession().workSound(); ++ SoundEvent soundeffect = this.getVillagerData().getProfession().workSound(); + +- if (soundevent != null) { +- this.playSound(soundevent, this.getSoundVolume(), this.getVoicePitch()); ++ if (soundeffect != null) { ++ this.playSound(soundeffect, this.getSoundVolume(), this.getVoicePitch()); + } + + } + + @Override +- @Override +- public void setVillagerData(VillagerData villagerdata) { ++ public void setVillagerData(VillagerData data) { + VillagerData villagerdata1 = this.getVillagerData(); + +- if (villagerdata1.getProfession() != villagerdata.getProfession()) { ++ if (villagerdata1.getProfession() != data.getProfession()) { + this.offers = null; + } + +- this.entityData.set(Villager.DATA_VILLAGER_DATA, villagerdata); ++ this.entityData.set(Villager.DATA_VILLAGER_DATA, data); + } + + @Override +- @Override + public VillagerData getVillagerData() { + return (VillagerData) this.entityData.get(Villager.DATA_VILLAGER_DATA); + } + + @Override +- @Override +- protected void rewardTradeXp(MerchantOffer merchantoffer) { ++ protected void rewardTradeXp(MerchantOffer offer) { + int i = 3 + this.random.nextInt(4); + +- this.villagerXp += merchantoffer.getXp(); ++ this.villagerXp += offer.getXp(); + this.lastTradedPlayer = this.getTradingPlayer(); + if (this.shouldIncreaseLevel()) { + this.updateMerchantTimer = 40; +@@ -628,14 +626,14 @@ + i += 5; + } + +- if (merchantoffer.shouldRewardExp()) { ++ if (offer.shouldRewardExp()) { + this.level().addFreshEntity(new ExperienceOrb(this.level(), this.getX(), this.getY() + 0.5D, this.getZ(), i)); + } + + } + +- public void setChasing(boolean flag) { +- this.chasing = flag; ++ public void setChasing(boolean chasing) { ++ this.chasing = chasing; + } + + public boolean isChasing() { +@@ -643,72 +641,70 @@ + } + + @Override +- @Override +- public void setLastHurtByMob(@Nullable LivingEntity livingentity) { +- if (livingentity != null && this.level() instanceof ServerLevel) { +- ((ServerLevel) this.level()).onReputationEvent(ReputationEventType.VILLAGER_HURT, livingentity, this); +- if (this.isAlive() && livingentity instanceof Player) { ++ public void setLastHurtByMob(@Nullable LivingEntity livingBase) { ++ if (livingBase != null && this.level() instanceof ServerLevel) { ++ ((ServerLevel) this.level()).onReputationEvent(ReputationEventType.VILLAGER_HURT, livingBase, this); ++ if (this.isAlive() && livingBase instanceof Player) { + this.level().broadcastEntityEvent(this, (byte) 13); + } + } + +- super.setLastHurtByMob(livingentity); ++ super.setLastHurtByMob(livingBase); + } + + @Override +- @Override +- public void die(DamageSource damagesource) { +- Villager.LOGGER.info("Villager {} died, message: '{}'", this, damagesource.getLocalizedDeathMessage(this).getString()); +- Entity entity = damagesource.getEntity(); ++ public void die(DamageSource cause) { ++ Villager.LOGGER.info("Villager {} died, message: '{}'", this, cause.getLocalizedDeathMessage(this).getString()); ++ Entity entity = cause.getEntity(); + + if (entity != null) { + this.tellWitnessesThatIWasMurdered(entity); + } + + this.releaseAllPois(); +- super.die(damagesource); ++ super.die(cause); + } + +- private void releaseAllPois() { ++ public void releaseAllPois() { + this.releasePoi(MemoryModuleType.HOME); + this.releasePoi(MemoryModuleType.JOB_SITE); + this.releasePoi(MemoryModuleType.POTENTIAL_JOB_SITE); + this.releasePoi(MemoryModuleType.MEETING_POINT); + } + +- private void tellWitnessesThatIWasMurdered(Entity entity) { +- Level level = this.level(); ++ private void tellWitnessesThatIWasMurdered(Entity murderer) { ++ Level world = this.level(); + +- if (level instanceof ServerLevel) { +- ServerLevel serverlevel = (ServerLevel) level; ++ if (world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; + Optional optional = this.brain.getMemory(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES); + + if (!optional.isEmpty()) { + NearestVisibleLivingEntities nearestvisiblelivingentities = (NearestVisibleLivingEntities) optional.get(); + + Objects.requireNonNull(ReputationEventHandler.class); +- nearestvisiblelivingentities.findAll(ReputationEventHandler.class::isInstance).forEach((livingentity) -> { +- serverlevel.onReputationEvent(ReputationEventType.VILLAGER_KILLED, entity, (ReputationEventHandler) livingentity); ++ nearestvisiblelivingentities.findAll(ReputationEventHandler.class::isInstance).forEach((entityliving) -> { ++ worldserver.onReputationEvent(ReputationEventType.VILLAGER_KILLED, murderer, (ReputationEventHandler) entityliving); + }); + } + } + } + +- public void releasePoi(MemoryModuleType<GlobalPos> memorymoduletype) { ++ public void releasePoi(MemoryModuleType<GlobalPos> moduleType) { + if (this.level() instanceof ServerLevel) { + MinecraftServer minecraftserver = ((ServerLevel) this.level()).getServer(); + +- this.brain.getMemory(memorymoduletype).ifPresent((globalpos) -> { +- ServerLevel serverlevel = minecraftserver.getLevel(globalpos.dimension()); ++ this.brain.getMemory(moduleType).ifPresent((globalpos) -> { ++ ServerLevel worldserver = minecraftserver.getLevel(globalpos.dimension()); + +- if (serverlevel != null) { +- PoiManager poimanager = serverlevel.getPoiManager(); +- Optional<Holder<PoiType>> optional = poimanager.getType(globalpos.pos()); +- BiPredicate<Villager, Holder<PoiType>> bipredicate = (BiPredicate) Villager.POI_MEMORIES.get(memorymoduletype); ++ if (worldserver != null) { ++ PoiManager villageplace = worldserver.getPoiManager(); ++ Optional<Holder<PoiType>> optional = villageplace.getType(globalpos.pos()); ++ BiPredicate<Villager, Holder<PoiType>> bipredicate = (BiPredicate) Villager.POI_MEMORIES.get(moduleType); + + if (optional.isPresent() && bipredicate.test(this, (Holder) optional.get())) { +- poimanager.release(globalpos.pos()); +- DebugPackets.sendPoiTicketCountPacket(serverlevel, globalpos.pos()); ++ villageplace.release(globalpos.pos()); ++ DebugPackets.sendPoiTicketCountPacket(worldserver, globalpos.pos()); + } + + } +@@ -717,7 +713,6 @@ + } + + @Override +- @Override + public boolean canBreed() { + return this.foodLevel + this.countFoodPointsInInventory() >= 12 && !this.isSleeping() && this.getAge() == 0; + } +@@ -752,13 +747,13 @@ + } + + public int getPlayerReputation(Player player) { +- return this.gossips.getReputation(player.getUUID(), (gossiptype) -> { ++ return this.gossips.getReputation(player.getUUID(), (reputationtype) -> { + return true; + }); + } + +- private void digestFood(int i) { +- this.foodLevel -= i; ++ private void digestFood(int qty) { ++ this.foodLevel -= qty; + } + + public void eatAndDigestFood() { +@@ -766,8 +761,8 @@ + this.digestFood(12); + } + +- public void setOffers(MerchantOffers merchantoffers) { +- this.offers = merchantoffers; ++ public void setOffers(MerchantOffers offers) { ++ this.offers = offers; + } + + private boolean shouldIncreaseLevel() { +@@ -776,13 +771,12 @@ + return VillagerData.canLevelUp(i) && this.villagerXp >= VillagerData.getMaxXpPerLevel(i); + } + +- private void increaseMerchantCareer() { ++ public void increaseMerchantCareer() { + this.setVillagerData(this.getVillagerData().setLevel(this.getVillagerData().getLevel() + 1)); + this.updateTrades(); + } + + @Override +- @Override + protected Component getTypeName() { + String s = this.getType().getDescriptionId(); + +@@ -790,103 +784,102 @@ + } + + @Override +- @Override +- public void handleEntityEvent(byte b0) { +- if (b0 == 12) { ++ public void handleEntityEvent(byte id) { ++ if (id == 12) { + this.addParticlesAroundSelf(ParticleTypes.HEART); +- } else if (b0 == 13) { ++ } else if (id == 13) { + this.addParticlesAroundSelf(ParticleTypes.ANGRY_VILLAGER); +- } else if (b0 == 14) { ++ } else if (id == 14) { + this.addParticlesAroundSelf(ParticleTypes.HAPPY_VILLAGER); +- } else if (b0 == 42) { ++ } else if (id == 42) { + this.addParticlesAroundSelf(ParticleTypes.SPLASH); + } else { +- super.handleEntityEvent(b0); ++ super.handleEntityEvent(id); + } + + } + + @Nullable + @Override +- @Override +- public SpawnGroupData finalizeSpawn(ServerLevelAccessor serverlevelaccessor, DifficultyInstance difficultyinstance, MobSpawnType mobspawntype, @Nullable SpawnGroupData spawngroupdata, @Nullable CompoundTag compoundtag) { +- if (mobspawntype == MobSpawnType.BREEDING) { ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ if (reason == EnumMobSpawn.BREEDING) { + this.setVillagerData(this.getVillagerData().setProfession(VillagerProfession.NONE)); + } + +- if (mobspawntype == MobSpawnType.COMMAND || mobspawntype == MobSpawnType.SPAWN_EGG || MobSpawnType.isSpawner(mobspawntype) || mobspawntype == MobSpawnType.DISPENSER) { +- this.setVillagerData(this.getVillagerData().setType(VillagerType.byBiome(serverlevelaccessor.getBiome(this.blockPosition())))); ++ if (reason == EnumMobSpawn.COMMAND || reason == EnumMobSpawn.SPAWN_EGG || EnumMobSpawn.isSpawner(reason) || reason == EnumMobSpawn.DISPENSER) { ++ this.setVillagerData(this.getVillagerData().setType(VillagerType.byBiome(level.getBiome(this.blockPosition())))); + } + +- if (mobspawntype == MobSpawnType.STRUCTURE) { ++ if (reason == EnumMobSpawn.STRUCTURE) { + this.assignProfessionWhenSpawned = true; + } + +- return super.finalizeSpawn(serverlevelaccessor, difficultyinstance, mobspawntype, spawngroupdata, compoundtag); ++ return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); + } + + @Nullable + @Override +- @Override +- public Villager getBreedOffspring(ServerLevel serverlevel, AgeableMob ageablemob) { ++ public Villager getBreedOffspring(ServerLevel level, AgeableMob otherParent) { + double d0 = this.random.nextDouble(); + VillagerType villagertype; + + if (d0 < 0.5D) { +- villagertype = VillagerType.byBiome(serverlevel.getBiome(this.blockPosition())); ++ villagertype = VillagerType.byBiome(level.getBiome(this.blockPosition())); + } else if (d0 < 0.75D) { + villagertype = this.getVillagerData().getType(); + } else { +- villagertype = ((Villager) ageablemob).getVillagerData().getType(); ++ villagertype = ((Villager) otherParent).getVillagerData().getType(); + } + +- Villager villager = new Villager(EntityType.VILLAGER, serverlevel, villagertype); ++ Villager entityvillager = new Villager(EntityType.VILLAGER, level, villagertype); + +- villager.finalizeSpawn(serverlevel, serverlevel.getCurrentDifficultyAt(villager.blockPosition()), MobSpawnType.BREEDING, (SpawnGroupData) null, (CompoundTag) null); +- return villager; ++ entityvillager.finalizeSpawn(level, level.getCurrentDifficultyAt(entityvillager.blockPosition()), EnumMobSpawn.BREEDING, (GroupDataEntity) null, (CompoundTag) null); ++ return entityvillager; + } + + @Override +- @Override +- public void thunderHit(ServerLevel serverlevel, LightningBolt lightningbolt) { +- if (serverlevel.getDifficulty() != Difficulty.PEACEFUL) { +- Villager.LOGGER.info("Villager {} was struck by lightning {}.", this, lightningbolt); +- Witch witch = (Witch) EntityType.WITCH.create(serverlevel); ++ public void thunderHit(ServerLevel level, LightningBolt lightning) { ++ if (level.getDifficulty() != Difficulty.PEACEFUL) { ++ Villager.LOGGER.info("Villager {} was struck by lightning {}.", this, lightning); ++ Witch entitywitch = (Witch) EntityType.WITCH.create(level); + +- if (witch != null) { +- witch.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); +- witch.finalizeSpawn(serverlevel, serverlevel.getCurrentDifficultyAt(witch.blockPosition()), MobSpawnType.CONVERSION, (SpawnGroupData) null, (CompoundTag) null); +- witch.setNoAi(this.isNoAi()); ++ if (entitywitch != null) { ++ entitywitch.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); ++ entitywitch.finalizeSpawn(level, level.getCurrentDifficultyAt(entitywitch.blockPosition()), EnumMobSpawn.CONVERSION, (GroupDataEntity) null, (CompoundTag) null); ++ entitywitch.setNoAi(this.isNoAi()); + if (this.hasCustomName()) { +- witch.setCustomName(this.getCustomName()); +- witch.setCustomNameVisible(this.isCustomNameVisible()); ++ entitywitch.setCustomName(this.getCustomName()); ++ entitywitch.setCustomNameVisible(this.isCustomNameVisible()); + } + +- witch.setPersistenceRequired(); +- serverlevel.addFreshEntityWithPassengers(witch); ++ entitywitch.setPersistenceRequired(); ++ // CraftBukkit start ++ if (CraftEventFactory.callEntityTransformEvent(this, entitywitch, EntityTransformEvent.TransformReason.LIGHTNING).isCancelled()) { ++ return; ++ } ++ level.addFreshEntityWithPassengers(entitywitch, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.LIGHTNING); ++ // CraftBukkit end + this.releaseAllPois(); + this.discard(); + } else { +- super.thunderHit(serverlevel, lightningbolt); ++ super.thunderHit(level, lightning); + } + } else { +- super.thunderHit(serverlevel, lightningbolt); ++ super.thunderHit(level, lightning); + } + + } + + @Override +- @Override +- protected void pickUpItem(ItemEntity itementity) { +- InventoryCarrier.pickUpItem(this, this, itementity); ++ protected void pickUpItem(ItemEntity itemEntity) { ++ InventoryCarrier.pickUpItem(this, this, itemEntity); + } + + @Override +- @Override +- public boolean wantsToPickUp(ItemStack itemstack) { +- Item item = itemstack.getItem(); ++ public boolean wantsToPickUp(ItemStack stack) { ++ Item item = stack.getItem(); + +- return (Villager.WANTED_ITEMS.contains(item) || this.getVillagerData().getProfession().requestedItems().contains(item)) && this.getInventory().canAddItem(itemstack); ++ return (Villager.WANTED_ITEMS.contains(item) || this.getVillagerData().getProfession().requestedItems().contains(item)) && this.getInventory().canAddItem(stack); + } + + public boolean hasExcessFood() { +@@ -898,10 +891,10 @@ + } + + private int countFoodPointsInInventory() { +- SimpleContainer simplecontainer = this.getInventory(); ++ SimpleContainer inventorysubcontainer = this.getInventory(); + + return Villager.FOOD_POINTS.entrySet().stream().mapToInt((entry) -> { +- return simplecontainer.countItem((Item) entry.getKey()) * (Integer) entry.getValue(); ++ return inventorysubcontainer.countItem((Item) entry.getKey()) * (Integer) entry.getValue(); + }).sum(); + } + +@@ -912,7 +905,6 @@ + } + + @Override +- @Override + protected void updateTrades() { + VillagerData villagerdata = this.getVillagerData(); + Int2ObjectMap int2objectmap; +@@ -926,22 +918,22 @@ + } + + if (int2objectmap != null && !int2objectmap.isEmpty()) { +- VillagerTrades.ItemListing[] avillagertrades_itemlisting = (VillagerTrades.ItemListing[]) int2objectmap.get(villagerdata.getLevel()); ++ VillagerTrades.ItemListing[] avillagertrades_imerchantrecipeoption = (VillagerTrades.ItemListing[]) int2objectmap.get(villagerdata.getLevel()); + +- if (avillagertrades_itemlisting != null) { +- MerchantOffers merchantoffers = this.getOffers(); ++ if (avillagertrades_imerchantrecipeoption != null) { ++ MerchantOffers merchantrecipelist = this.getOffers(); + +- this.addOffersFromItemListings(merchantoffers, avillagertrades_itemlisting, 2); ++ this.addOffersFromItemListings(merchantrecipelist, avillagertrades_imerchantrecipeoption, 2); + } + } + } + +- public void gossip(ServerLevel serverlevel, Villager villager, long i) { +- if ((i < this.lastGossipTime || i >= this.lastGossipTime + 1200L) && (i < villager.lastGossipTime || i >= villager.lastGossipTime + 1200L)) { +- this.gossips.transferFrom(villager.gossips, this.random, 10); +- this.lastGossipTime = i; +- villager.lastGossipTime = i; +- this.spawnGolemIfNeeded(serverlevel, i, 5); ++ public void gossip(ServerLevel serverLevel, Villager target, long gameTime) { ++ if ((gameTime < this.lastGossipTime || gameTime >= this.lastGossipTime + 1200L) && (gameTime < target.lastGossipTime || gameTime >= target.lastGossipTime + 1200L)) { ++ this.gossips.transferFrom(target.gossips, this.random, 10); ++ this.lastGossipTime = gameTime; ++ target.lastGossipTime = gameTime; ++ this.spawnGolemIfNeeded(serverLevel, gameTime, 5); + } + } + +@@ -956,50 +948,48 @@ + } + } + +- public void spawnGolemIfNeeded(ServerLevel serverlevel, long i, int j) { +- if (this.wantsToSpawnGolem(i)) { +- AABB aabb = this.getBoundingBox().inflate(10.0D, 10.0D, 10.0D); +- List<Villager> list = serverlevel.getEntitiesOfClass(Villager.class, aabb); +- List<Villager> list1 = (List) list.stream().filter((villager) -> { +- return villager.wantsToSpawnGolem(i); ++ public void spawnGolemIfNeeded(ServerLevel serverLevel, long gameTime, int j) { ++ if (this.wantsToSpawnGolem(gameTime)) { ++ AABB axisalignedbb = this.getBoundingBox().inflate(10.0D, 10.0D, 10.0D); ++ List<Villager> list = serverLevel.getEntitiesOfClass(Villager.class, axisalignedbb); ++ List<Villager> list1 = (List) list.stream().filter((entityvillager) -> { ++ return entityvillager.wantsToSpawnGolem(gameTime); + }).limit(5L).collect(Collectors.toList()); + + if (list1.size() >= j) { +- if (!SpawnUtil.trySpawnMob(EntityType.IRON_GOLEM, MobSpawnType.MOB_SUMMONED, serverlevel, this.blockPosition(), 10, 8, 6, SpawnUtil.Strategy.LEGACY_IRON_GOLEM).isEmpty()) { ++ if (!SpawnUtil.trySpawnMob(EntityType.IRON_GOLEM, EnumMobSpawn.MOB_SUMMONED, serverLevel, this.blockPosition(), 10, 8, 6, SpawnUtil.Strategy.LEGACY_IRON_GOLEM, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.VILLAGE_DEFENSE).isEmpty()) { // CraftBukkit + list.forEach(GolemSensor::golemDetected); + } + } + } + } + +- public boolean wantsToSpawnGolem(long i) { ++ public boolean wantsToSpawnGolem(long gameTime) { + return !this.golemSpawnConditionsMet(this.level().getGameTime()) ? false : !this.brain.hasMemoryValue(MemoryModuleType.GOLEM_DETECTED_RECENTLY); + } + + @Override +- @Override +- public void onReputationEventFrom(ReputationEventType reputationeventtype, Entity entity) { +- if (reputationeventtype == ReputationEventType.ZOMBIE_VILLAGER_CURED) { +- this.gossips.add(entity.getUUID(), GossipType.MAJOR_POSITIVE, 20); +- this.gossips.add(entity.getUUID(), GossipType.MINOR_POSITIVE, 25); +- } else if (reputationeventtype == ReputationEventType.TRADE) { +- this.gossips.add(entity.getUUID(), GossipType.TRADING, 2); +- } else if (reputationeventtype == ReputationEventType.VILLAGER_HURT) { +- this.gossips.add(entity.getUUID(), GossipType.MINOR_NEGATIVE, 25); +- } else if (reputationeventtype == ReputationEventType.VILLAGER_KILLED) { +- this.gossips.add(entity.getUUID(), GossipType.MAJOR_NEGATIVE, 25); ++ public void onReputationEventFrom(ReputationEventType type, Entity target) { ++ if (type == ReputationEventType.ZOMBIE_VILLAGER_CURED) { ++ this.gossips.add(target.getUUID(), GossipType.MAJOR_POSITIVE, 20); ++ this.gossips.add(target.getUUID(), GossipType.MINOR_POSITIVE, 25); ++ } else if (type == ReputationEventType.TRADE) { ++ this.gossips.add(target.getUUID(), GossipType.TRADING, 2); ++ } else if (type == ReputationEventType.VILLAGER_HURT) { ++ this.gossips.add(target.getUUID(), GossipType.MINOR_NEGATIVE, 25); ++ } else if (type == ReputationEventType.VILLAGER_KILLED) { ++ this.gossips.add(target.getUUID(), GossipType.MAJOR_NEGATIVE, 25); + } + + } + + @Override +- @Override + public int getVillagerXp() { + return this.villagerXp; + } + +- public void setVillagerXp(int i) { +- this.villagerXp = i; ++ public void setVillagerXp(int villagerXp) { ++ this.villagerXp = villagerXp; + } + + private void resetNumberOfRestocks() { +@@ -1011,36 +1001,33 @@ + return this.gossips; + } + +- public void setGossips(Tag tag) { +- this.gossips.update(new Dynamic(NbtOps.INSTANCE, tag)); ++ public void setGossips(Tag gossip) { ++ this.gossips.update(new Dynamic(NbtOps.INSTANCE, gossip)); + } + + @Override +- @Override + protected void sendDebugPackets() { + super.sendDebugPackets(); + DebugPackets.sendEntityBrain(this); + } + + @Override +- @Override +- public void startSleeping(BlockPos blockpos) { +- super.startSleeping(blockpos); +- this.brain.setMemory(MemoryModuleType.LAST_SLEPT, (Object) this.level().getGameTime()); ++ public void startSleeping(BlockPos pos) { ++ super.startSleeping(pos); ++ this.brain.setMemory(MemoryModuleType.LAST_SLEPT, this.level().getGameTime()); // CraftBukkit - decompile error + this.brain.eraseMemory(MemoryModuleType.WALK_TARGET); + this.brain.eraseMemory(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE); + } + + @Override +- @Override + public void stopSleeping() { + super.stopSleeping(); +- this.brain.setMemory(MemoryModuleType.LAST_WOKEN, (Object) this.level().getGameTime()); ++ this.brain.setMemory(MemoryModuleType.LAST_WOKEN, this.level().getGameTime()); // CraftBukkit - decompile error + } + +- private boolean golemSpawnConditionsMet(long i) { ++ private boolean golemSpawnConditionsMet(long gameTime) { + Optional<Long> optional = this.brain.getMemory(MemoryModuleType.LAST_SLEPT); + +- return optional.isPresent() ? i - (Long) optional.get() < 24000L : false; ++ return optional.isPresent() ? gameTime - (Long) optional.get() < 24000L : false; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/npc/WanderingTrader.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/npc/WanderingTrader.java.patch new file mode 100644 index 0000000000..1977fd62f4 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/npc/WanderingTrader.java.patch @@ -0,0 +1,356 @@ +--- a/net/minecraft/world/entity/npc/WanderingTrader.java ++++ b/net/minecraft/world/entity/npc/WanderingTrader.java +@@ -10,7 +10,7 @@ + import net.minecraft.sounds.SoundEvent; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.stats.Stats; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.AgeableMob; +@@ -20,11 +20,11 @@ + import net.minecraft.world.entity.ai.goal.AvoidEntityGoal; + import net.minecraft.world.entity.ai.goal.FloatGoal; + import net.minecraft.world.entity.ai.goal.Goal; +-import net.minecraft.world.entity.ai.goal.InteractGoal; + import net.minecraft.world.entity.ai.goal.LookAtPlayerGoal; + import net.minecraft.world.entity.ai.goal.LookAtTradingPlayerGoal; + import net.minecraft.world.entity.ai.goal.MoveTowardsRestrictionGoal; + import net.minecraft.world.entity.ai.goal.PanicGoal; ++import net.minecraft.world.entity.ai.goal.PathfinderGoalInteract; + import net.minecraft.world.entity.ai.goal.TradeWithPlayerGoal; + import net.minecraft.world.entity.ai.goal.UseItemGoal; + import net.minecraft.world.entity.ai.goal.WaterAvoidingRandomStrollGoal; +@@ -47,26 +47,33 @@ + import net.minecraft.world.phys.Vec3; + import org.apache.commons.lang3.tuple.Pair; + +-public class WanderingTrader extends AbstractVillager { ++// CraftBukkit start ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.inventory.CraftMerchantRecipe; ++import org.bukkit.entity.AbstractVillager; ++import org.bukkit.event.entity.VillagerAcquireTradeEvent; ++// CraftBukkit end + ++public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVillager { ++ + private static final int NUMBER_OF_TRADE_OFFERS = 5; + @Nullable + private BlockPos wanderTarget; + private int despawnDelay; + +- public WanderingTrader(EntityType<? extends WanderingTrader> entitytype, Level level) { +- super(entitytype, level); ++ public WanderingTrader(EntityType<? extends WanderingTrader> entityType, Level level) { ++ super(entityType, level); ++ this.setDespawnDelay(48000); // CraftBukkit - set default from MobSpawnerTrader + } + + @Override +- @Override + protected void registerGoals() { + this.goalSelector.addGoal(0, new FloatGoal(this)); +- this.goalSelector.addGoal(0, new UseItemGoal<>(this, PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.INVISIBILITY), SoundEvents.WANDERING_TRADER_DISAPPEARED, (wanderingtrader) -> { +- return this.level().isNight() && !wanderingtrader.isInvisible(); ++ this.goalSelector.addGoal(0, new UseItemGoal<>(this, PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.INVISIBILITY), SoundEvents.WANDERING_TRADER_DISAPPEARED, (entityvillagertrader) -> { ++ return this.level().isNight() && !entityvillagertrader.isInvisible(); + })); +- this.goalSelector.addGoal(0, new UseItemGoal<>(this, new ItemStack(Items.MILK_BUCKET), SoundEvents.WANDERING_TRADER_REAPPEARED, (wanderingtrader) -> { +- return this.level().isDay() && wanderingtrader.isInvisible(); ++ this.goalSelector.addGoal(0, new UseItemGoal<>(this, new ItemStack(Items.MILK_BUCKET), SoundEvents.WANDERING_TRADER_REAPPEARED, (entityvillagertrader) -> { ++ return this.level().isDay() && entityvillagertrader.isInvisible(); + })); + this.goalSelector.addGoal(1, new TradeWithPlayerGoal(this)); + this.goalSelector.addGoal(1, new AvoidEntityGoal<>(this, Zombie.class, 8.0F, 0.5D, 0.5D)); +@@ -81,30 +88,27 @@ + this.goalSelector.addGoal(2, new WanderingTrader.WanderToPositionGoal(this, 2.0D, 0.35D)); + this.goalSelector.addGoal(4, new MoveTowardsRestrictionGoal(this, 0.35D)); + this.goalSelector.addGoal(8, new WaterAvoidingRandomStrollGoal(this, 0.35D)); +- this.goalSelector.addGoal(9, new InteractGoal(this, Player.class, 3.0F, 1.0F)); ++ this.goalSelector.addGoal(9, new PathfinderGoalInteract(this, Player.class, 3.0F, 1.0F)); + this.goalSelector.addGoal(10, new LookAtPlayerGoal(this, Mob.class, 8.0F)); + } + + @Nullable + @Override +- @Override +- public AgeableMob getBreedOffspring(ServerLevel serverlevel, AgeableMob ageablemob) { ++ public AgeableMob getBreedOffspring(ServerLevel level, AgeableMob otherParent) { + return null; + } + + @Override +- @Override + public boolean showProgressBar() { + return false; + } + + @Override +- @Override +- public InteractionResult mobInteract(Player player, InteractionHand interactionhand) { +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); + + if (!itemstack.is(Items.VILLAGER_SPAWN_EGG) && this.isAlive() && !this.isTrading() && !this.isBaby()) { +- if (interactionhand == InteractionHand.MAIN_HAND) { ++ if (hand == EnumHand.MAIN_HAND) { + player.awardStat(Stats.TALKED_TO_VILLAGER); + } + +@@ -119,29 +123,37 @@ + return InteractionResult.sidedSuccess(this.level().isClientSide); + } + } else { +- return super.mobInteract(player, interactionhand); ++ return super.mobInteract(player, hand); + } + } + + @Override +- @Override + protected void updateTrades() { + if (this.level().enabledFeatures().contains(FeatureFlags.TRADE_REBALANCE)) { + this.experimentalUpdateTrades(); + } else { +- VillagerTrades.ItemListing[] avillagertrades_itemlisting = (VillagerTrades.ItemListing[]) VillagerTrades.WANDERING_TRADER_TRADES.get(1); +- VillagerTrades.ItemListing[] avillagertrades_itemlisting1 = (VillagerTrades.ItemListing[]) VillagerTrades.WANDERING_TRADER_TRADES.get(2); ++ VillagerTrades.ItemListing[] avillagertrades_imerchantrecipeoption = (VillagerTrades.ItemListing[]) VillagerTrades.WANDERING_TRADER_TRADES.get(1); ++ VillagerTrades.ItemListing[] avillagertrades_imerchantrecipeoption1 = (VillagerTrades.ItemListing[]) VillagerTrades.WANDERING_TRADER_TRADES.get(2); + +- if (avillagertrades_itemlisting != null && avillagertrades_itemlisting1 != null) { +- MerchantOffers merchantoffers = this.getOffers(); ++ if (avillagertrades_imerchantrecipeoption != null && avillagertrades_imerchantrecipeoption1 != null) { ++ MerchantOffers merchantrecipelist = this.getOffers(); + +- this.addOffersFromItemListings(merchantoffers, avillagertrades_itemlisting, 5); +- int i = this.random.nextInt(avillagertrades_itemlisting1.length); +- VillagerTrades.ItemListing villagertrades_itemlisting = avillagertrades_itemlisting1[i]; +- MerchantOffer merchantoffer = villagertrades_itemlisting.getOffer(this, this.random); ++ this.addOffersFromItemListings(merchantrecipelist, avillagertrades_imerchantrecipeoption, 5); ++ int i = this.random.nextInt(avillagertrades_imerchantrecipeoption1.length); ++ VillagerTrades.ItemListing villagertrades_imerchantrecipeoption = avillagertrades_imerchantrecipeoption1[i]; ++ MerchantOffer merchantrecipe = villagertrades_imerchantrecipeoption.getOffer(this, this.random); + +- if (merchantoffer != null) { +- merchantoffers.add(merchantoffer); ++ if (merchantrecipe != null) { ++ // CraftBukkit start ++ VillagerAcquireTradeEvent event = new VillagerAcquireTradeEvent((AbstractVillager) getBukkitEntity(), merchantrecipe.asBukkit()); ++ // Suppress during worldgen ++ if (this.valid) { ++ Bukkit.getPluginManager().callEvent(event); ++ } ++ if (!event.isCancelled()) { ++ merchantrecipelist.add(CraftMerchantRecipe.fromBukkit(event.getRecipe()).toMinecraft()); ++ } ++ // CraftBukkit end + } + + } +@@ -149,54 +161,50 @@ + } + + private void experimentalUpdateTrades() { +- MerchantOffers merchantoffers = this.getOffers(); ++ MerchantOffers merchantrecipelist = this.getOffers(); + Iterator iterator = VillagerTrades.EXPERIMENTAL_WANDERING_TRADER_TRADES.iterator(); + + while (iterator.hasNext()) { + Pair<VillagerTrades.ItemListing[], Integer> pair = (Pair) iterator.next(); +- VillagerTrades.ItemListing[] avillagertrades_itemlisting = (VillagerTrades.ItemListing[]) pair.getLeft(); ++ VillagerTrades.ItemListing[] avillagertrades_imerchantrecipeoption = (VillagerTrades.ItemListing[]) pair.getLeft(); + +- this.addOffersFromItemListings(merchantoffers, avillagertrades_itemlisting, (Integer) pair.getRight()); ++ this.addOffersFromItemListings(merchantrecipelist, avillagertrades_imerchantrecipeoption, (Integer) pair.getRight()); + } + + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putInt("DespawnDelay", this.despawnDelay); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putInt("DespawnDelay", this.despawnDelay); + if (this.wanderTarget != null) { +- compoundtag.put("WanderTarget", NbtUtils.writeBlockPos(this.wanderTarget)); ++ compound.put("WanderTarget", NbtUtils.writeBlockPos(this.wanderTarget)); + } + + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- if (compoundtag.contains("DespawnDelay", 99)) { +- this.despawnDelay = compoundtag.getInt("DespawnDelay"); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ if (compound.contains("DespawnDelay", 99)) { ++ this.despawnDelay = compound.getInt("DespawnDelay"); + } + +- if (compoundtag.contains("WanderTarget")) { +- this.wanderTarget = NbtUtils.readBlockPos(compoundtag.getCompound("WanderTarget")); ++ if (compound.contains("WanderTarget")) { ++ this.wanderTarget = NbtUtils.readBlockPos(compound.getCompound("WanderTarget")); + } + + this.setAge(Math.max(0, this.getAge())); + } + + @Override +- @Override +- public boolean removeWhenFarAway(double d0) { ++ public boolean removeWhenFarAway(double distanceToClosestPlayer) { + return false; + } + + @Override +- @Override +- protected void rewardTradeXp(MerchantOffer merchantoffer) { +- if (merchantoffer.shouldRewardExp()) { ++ protected void rewardTradeXp(MerchantOffer offer) { ++ if (offer.shouldRewardExp()) { + int i = 3 + this.random.nextInt(4); + + this.level().addFreshEntity(new ExperienceOrb(this.level(), this.getX(), this.getY() + 0.5D, this.getZ(), i)); +@@ -205,43 +213,37 @@ + } + + @Override +- @Override + protected SoundEvent getAmbientSound() { + return this.isTrading() ? SoundEvents.WANDERING_TRADER_TRADE : SoundEvents.WANDERING_TRADER_AMBIENT; + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.WANDERING_TRADER_HURT; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.WANDERING_TRADER_DEATH; + } + + @Override +- @Override +- protected SoundEvent getDrinkingSound(ItemStack itemstack) { +- return itemstack.is(Items.MILK_BUCKET) ? SoundEvents.WANDERING_TRADER_DRINK_MILK : SoundEvents.WANDERING_TRADER_DRINK_POTION; ++ protected SoundEvent getDrinkingSound(ItemStack stack) { ++ return stack.is(Items.MILK_BUCKET) ? SoundEvents.WANDERING_TRADER_DRINK_MILK : SoundEvents.WANDERING_TRADER_DRINK_POTION; + } + + @Override +- @Override +- protected SoundEvent getTradeUpdatedSound(boolean flag) { +- return flag ? SoundEvents.WANDERING_TRADER_YES : SoundEvents.WANDERING_TRADER_NO; ++ protected SoundEvent getTradeUpdatedSound(boolean getYesSound) { ++ return getYesSound ? SoundEvents.WANDERING_TRADER_YES : SoundEvents.WANDERING_TRADER_NO; + } + + @Override +- @Override + public SoundEvent getNotifyTradeSound() { + return SoundEvents.WANDERING_TRADER_YES; + } + +- public void setDespawnDelay(int i) { +- this.despawnDelay = i; ++ public void setDespawnDelay(int despawnDelay) { ++ this.despawnDelay = despawnDelay; + } + + public int getDespawnDelay() { +@@ -249,7 +251,6 @@ + } + + @Override +- @Override + public void aiStep() { + super.aiStep(); + if (!this.level().isClientSide) { +@@ -265,8 +266,8 @@ + + } + +- public void setWanderTarget(@Nullable BlockPos blockpos) { +- this.wanderTarget = blockpos; ++ public void setWanderTarget(@Nullable BlockPos wanderTarget) { ++ this.wanderTarget = wanderTarget; + } + + @Nullable +@@ -280,48 +281,45 @@ + final double stopDistance; + final double speedModifier; + +- WanderToPositionGoal(WanderingTrader wanderingtrader, double d0, double d1) { +- this.trader = wanderingtrader; ++ WanderToPositionGoal(WanderingTrader entityvillagertrader, double d0, double d1) { ++ this.trader = entityvillagertrader; + this.stopDistance = d0; + this.speedModifier = d1; +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); + } + + @Override +- @Override + public void stop() { + this.trader.setWanderTarget((BlockPos) null); + WanderingTrader.this.navigation.stop(); + } + + @Override +- @Override + public boolean canUse() { +- BlockPos blockpos = this.trader.getWanderTarget(); ++ BlockPos blockposition = this.trader.getWanderTarget(); + +- return blockpos != null && this.isTooFarAway(blockpos, this.stopDistance); ++ return blockposition != null && this.isTooFarAway(blockposition, this.stopDistance); + } + + @Override +- @Override + public void tick() { +- BlockPos blockpos = this.trader.getWanderTarget(); ++ BlockPos blockposition = this.trader.getWanderTarget(); + +- if (blockpos != null && WanderingTrader.this.navigation.isDone()) { +- if (this.isTooFarAway(blockpos, 10.0D)) { +- Vec3 vec3 = (new Vec3((double) blockpos.getX() - this.trader.getX(), (double) blockpos.getY() - this.trader.getY(), (double) blockpos.getZ() - this.trader.getZ())).normalize(); +- Vec3 vec31 = vec3.scale(10.0D).add(this.trader.getX(), this.trader.getY(), this.trader.getZ()); ++ if (blockposition != null && WanderingTrader.this.navigation.isDone()) { ++ if (this.isTooFarAway(blockposition, 10.0D)) { ++ Vec3 vec3d = (new Vec3((double) blockposition.getX() - this.trader.getX(), (double) blockposition.getY() - this.trader.getY(), (double) blockposition.getZ() - this.trader.getZ())).normalize(); ++ Vec3 vec3d1 = vec3d.scale(10.0D).add(this.trader.getX(), this.trader.getY(), this.trader.getZ()); + +- WanderingTrader.this.navigation.moveTo(vec31.x, vec31.y, vec31.z, this.speedModifier); ++ WanderingTrader.this.navigation.moveTo(vec3d1.x, vec3d1.y, vec3d1.z, this.speedModifier); + } else { +- WanderingTrader.this.navigation.moveTo((double) blockpos.getX(), (double) blockpos.getY(), (double) blockpos.getZ(), this.speedModifier); ++ WanderingTrader.this.navigation.moveTo((double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), this.speedModifier); + } + } + + } + +- private boolean isTooFarAway(BlockPos blockpos, double d0) { +- return !blockpos.closerToCenterThan(this.trader.position(), d0); ++ private boolean isTooFarAway(BlockPos pos, double distance) { ++ return !pos.closerToCenterThan(this.trader.position(), distance); + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/npc/WanderingTraderSpawner.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/npc/WanderingTraderSpawner.java.patch new file mode 100644 index 0000000000..6a29452482 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/npc/WanderingTraderSpawner.java.patch @@ -0,0 +1,193 @@ +--- a/net/minecraft/world/entity/npc/WanderingTraderSpawner.java ++++ b/net/minecraft/world/entity/npc/WanderingTraderSpawner.java +@@ -10,7 +10,7 @@ + import net.minecraft.util.Mth; + import net.minecraft.util.RandomSource; + import net.minecraft.world.entity.EntityType; +-import net.minecraft.world.entity.MobSpawnType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.SpawnPlacements; + import net.minecraft.world.entity.ai.village.poi.PoiManager; + import net.minecraft.world.entity.ai.village.poi.PoiTypes; +@@ -38,24 +38,23 @@ + private int spawnDelay; + private int spawnChance; + +- public WanderingTraderSpawner(ServerLevelData serverleveldata) { +- this.serverLevelData = serverleveldata; ++ public WanderingTraderSpawner(ServerLevelData serverLevelData) { ++ this.serverLevelData = serverLevelData; + this.tickDelay = 1200; +- this.spawnDelay = serverleveldata.getWanderingTraderSpawnDelay(); +- this.spawnChance = serverleveldata.getWanderingTraderSpawnChance(); ++ this.spawnDelay = serverLevelData.getWanderingTraderSpawnDelay(); ++ this.spawnChance = serverLevelData.getWanderingTraderSpawnChance(); + if (this.spawnDelay == 0 && this.spawnChance == 0) { + this.spawnDelay = 24000; +- serverleveldata.setWanderingTraderSpawnDelay(this.spawnDelay); ++ serverLevelData.setWanderingTraderSpawnDelay(this.spawnDelay); + this.spawnChance = 25; +- serverleveldata.setWanderingTraderSpawnChance(this.spawnChance); ++ serverLevelData.setWanderingTraderSpawnChance(this.spawnChance); + } + + } + + @Override +- @Override +- public int tick(ServerLevel serverlevel, boolean flag, boolean flag1) { +- if (!serverlevel.getGameRules().getBoolean(GameRules.RULE_DO_TRADER_SPAWNING)) { ++ public int tick(ServerLevel level, boolean spawnHostiles, boolean spawnPassives) { ++ if (!level.getGameRules().getBoolean(GameRules.RULE_DO_TRADER_SPAWNING)) { + return 0; + } else if (--this.tickDelay > 0) { + return 0; +@@ -67,7 +66,7 @@ + return 0; + } else { + this.spawnDelay = 24000; +- if (!serverlevel.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING)) { ++ if (!level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING)) { + return 0; + } else { + int i = this.spawnChance; +@@ -76,7 +75,7 @@ + this.serverLevelData.setWanderingTraderSpawnChance(this.spawnChance); + if (this.random.nextInt(100) > i) { + return 0; +- } else if (this.spawn(serverlevel)) { ++ } else if (this.spawn(level)) { + this.spawnChance = 25; + return 1; + } else { +@@ -87,41 +86,41 @@ + } + } + +- private boolean spawn(ServerLevel serverlevel) { +- ServerPlayer serverplayer = serverlevel.getRandomPlayer(); ++ private boolean spawn(ServerLevel serverLevel) { ++ ServerPlayer entityplayer = serverLevel.getRandomPlayer(); + +- if (serverplayer == null) { ++ if (entityplayer == null) { + return true; + } else if (this.random.nextInt(10) != 0) { + return false; + } else { +- BlockPos blockpos = serverplayer.blockPosition(); ++ BlockPos blockposition = entityplayer.blockPosition(); + boolean flag = true; +- PoiManager poimanager = serverlevel.getPoiManager(); +- Optional<BlockPos> optional = poimanager.find((holder) -> { ++ PoiManager villageplace = serverLevel.getPoiManager(); ++ Optional<BlockPos> optional = villageplace.find((holder) -> { + return holder.is(PoiTypes.MEETING); +- }, (blockpos1) -> { ++ }, (blockposition1) -> { + return true; +- }, blockpos, 48, PoiManager.Occupancy.ANY); +- BlockPos blockpos1 = (BlockPos) optional.orElse(blockpos); +- BlockPos blockpos2 = this.findSpawnPositionNear(serverlevel, blockpos1, 48); ++ }, blockposition, 48, PoiManager.Occupancy.ANY); ++ BlockPos blockposition1 = (BlockPos) optional.orElse(blockposition); ++ BlockPos blockposition2 = this.findSpawnPositionNear(serverLevel, blockposition1, 48); + +- if (blockpos2 != null && this.hasEnoughSpace(serverlevel, blockpos2)) { +- if (serverlevel.getBiome(blockpos2).is(BiomeTags.WITHOUT_WANDERING_TRADER_SPAWNS)) { ++ if (blockposition2 != null && this.hasEnoughSpace(serverLevel, blockposition2)) { ++ if (serverLevel.getBiome(blockposition2).is(BiomeTags.WITHOUT_WANDERING_TRADER_SPAWNS)) { + return false; + } + +- WanderingTrader wanderingtrader = (WanderingTrader) EntityType.WANDERING_TRADER.spawn(serverlevel, blockpos2, MobSpawnType.EVENT); ++ WanderingTrader entityvillagertrader = (WanderingTrader) EntityType.WANDERING_TRADER.spawn(serverLevel, blockposition2, EnumMobSpawn.EVENT, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit + +- if (wanderingtrader != null) { ++ if (entityvillagertrader != null) { + for (int i = 0; i < 2; ++i) { +- this.tryToSpawnLlamaFor(serverlevel, wanderingtrader, 4); ++ this.tryToSpawnLlamaFor(serverLevel, entityvillagertrader, 4); + } + +- this.serverLevelData.setWanderingTraderId(wanderingtrader.getUUID()); +- wanderingtrader.setDespawnDelay(48000); +- wanderingtrader.setWanderTarget(blockpos1); +- wanderingtrader.restrictTo(blockpos1, 16); ++ this.serverLevelData.setWanderingTraderId(entityvillagertrader.getUUID()); ++ // entityvillagertrader.setDespawnDelay(48000); // CraftBukkit - moved to EntityVillagerTrader constructor. This lets the value be modified by plugins on CreatureSpawnEvent ++ entityvillagertrader.setWanderTarget(blockposition1); ++ entityvillagertrader.restrictTo(blockposition1, 16); + return true; + } + } +@@ -130,49 +129,49 @@ + } + } + +- private void tryToSpawnLlamaFor(ServerLevel serverlevel, WanderingTrader wanderingtrader, int i) { +- BlockPos blockpos = this.findSpawnPositionNear(serverlevel, wanderingtrader.blockPosition(), i); ++ private void tryToSpawnLlamaFor(ServerLevel serverLevel, WanderingTrader trader, int maxDistance) { ++ BlockPos blockposition = this.findSpawnPositionNear(serverLevel, trader.blockPosition(), maxDistance); + +- if (blockpos != null) { +- TraderLlama traderllama = (TraderLlama) EntityType.TRADER_LLAMA.spawn(serverlevel, blockpos, MobSpawnType.EVENT); ++ if (blockposition != null) { ++ TraderLlama entityllamatrader = (TraderLlama) EntityType.TRADER_LLAMA.spawn(serverLevel, blockposition, EnumMobSpawn.EVENT, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit + +- if (traderllama != null) { +- traderllama.setLeashedTo(wanderingtrader, true); ++ if (entityllamatrader != null) { ++ entityllamatrader.setLeashedTo(trader, true); + } + } + } + + @Nullable +- private BlockPos findSpawnPositionNear(LevelReader levelreader, BlockPos blockpos, int i) { +- BlockPos blockpos1 = null; ++ private BlockPos findSpawnPositionNear(LevelReader level, BlockPos pos, int maxDistance) { ++ BlockPos blockposition1 = null; + + for (int j = 0; j < 10; ++j) { +- int k = blockpos.getX() + this.random.nextInt(i * 2) - i; +- int l = blockpos.getZ() + this.random.nextInt(i * 2) - i; +- int i1 = levelreader.getHeight(Heightmap.Types.WORLD_SURFACE, k, l); +- BlockPos blockpos2 = new BlockPos(k, i1, l); ++ int k = pos.getX() + this.random.nextInt(maxDistance * 2) - maxDistance; ++ int l = pos.getZ() + this.random.nextInt(maxDistance * 2) - maxDistance; ++ int i1 = level.getHeight(Heightmap.Types.WORLD_SURFACE, k, l); ++ BlockPos blockposition2 = new BlockPos(k, i1, l); + +- if (NaturalSpawner.isSpawnPositionOk(SpawnPlacements.Type.ON_GROUND, levelreader, blockpos2, EntityType.WANDERING_TRADER)) { +- blockpos1 = blockpos2; ++ if (NaturalSpawner.isSpawnPositionOk(SpawnPlacements.Surface.ON_GROUND, level, blockposition2, EntityType.WANDERING_TRADER)) { ++ blockposition1 = blockposition2; + break; + } + } + +- return blockpos1; ++ return blockposition1; + } + +- private boolean hasEnoughSpace(BlockGetter blockgetter, BlockPos blockpos) { +- Iterator iterator = BlockPos.betweenClosed(blockpos, blockpos.offset(1, 2, 1)).iterator(); ++ private boolean hasEnoughSpace(BlockGetter level, BlockPos pos) { ++ Iterator iterator = BlockPos.betweenClosed(pos, pos.offset(1, 2, 1)).iterator(); + +- BlockPos blockpos1; ++ BlockPos blockposition1; + + do { + if (!iterator.hasNext()) { + return true; + } + +- blockpos1 = (BlockPos) iterator.next(); +- } while (blockgetter.getBlockState(blockpos1).getCollisionShape(blockgetter, blockpos1).isEmpty()); ++ blockposition1 = (BlockPos) iterator.next(); ++ } while (level.getBlockState(blockposition1).getCollisionShape(level, blockposition1).isEmpty()); + + return false; + } |