diff --git a/paper-server/patches/sources/net/minecraft/world/entity/npc/Villager.java.patch b/paper-server/patches/sources/net/minecraft/world/entity/npc/Villager.java.patch index 608b0c1d5c..cb4983a642 100644 --- a/paper-server/patches/sources/net/minecraft/world/entity/npc/Villager.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/entity/npc/Villager.java.patch @@ -24,25 +24,25 @@ } @Override -@@ -214,7 +222,18 @@ - - public boolean assignProfessionWhenSpawned() { +@@ -216,7 +224,18 @@ return this.assignProfessionWhenSpawned; -+ } -+ + } + + // Spigot Start -+ @Override + @Override + public void inactiveTick() { + // SPIGOT-3874, SPIGOT-3894, SPIGOT-3846, SPIGOT-5286 :( + if (this.level().spigotConfig.tickInactiveVillagers && this.isEffectiveAi()) { + this.customServerAiStep((ServerLevel) this.level()); + } + super.inactiveTick(); - } ++ } + // Spigot End - - @Override ++ ++ @Override protected void customServerAiStep(ServerLevel world) { + ProfilerFiller gameprofilerfiller = Profiler.get(); + @@ -235,7 +254,7 @@ this.increaseProfessionLevelOnUpdate = false; } @@ -156,7 +156,33 @@ if (entitywitch == null) { super.thunderHit(world, lightning); -@@ -906,7 +946,7 @@ +@@ -855,6 +895,12 @@ + + @Override + protected void updateTrades() { ++ // Paper start - More vanilla friendly methods to update trades ++ updateTrades(TRADES_PER_LEVEL); ++ } ++ ++ public boolean updateTrades(int amount) { ++ // Paper end - More vanilla friendly methods to update trades + VillagerData villagerdata = this.getVillagerData(); + Int2ObjectMap int2objectmap; + +@@ -872,9 +918,11 @@ + if (avillagertrades_imerchantrecipeoption != null) { + MerchantOffers merchantrecipelist = this.getOffers(); + +- this.addOffersFromItemListings(merchantrecipelist, avillagertrades_imerchantrecipeoption, 2); ++ this.addOffersFromItemListings(merchantrecipelist, avillagertrades_imerchantrecipeoption, amount); // Paper - More vanilla friendly methods to update trades ++ return true; // Paper - More vanilla friendly methods to update trades + } + } ++ return false; // Paper - More vanilla friendly methods to update trades + } + + public void gossip(ServerLevel world, Villager villager, long time) { +@@ -906,7 +954,7 @@ }).limit(5L).toList(); if (list1.size() >= requiredCount) { @@ -165,7 +191,7 @@ list.forEach(GolemSensor::golemDetected); } } -@@ -963,7 +1003,7 @@ +@@ -963,7 +1011,7 @@ @Override public void startSleeping(BlockPos pos) { super.startSleeping(pos); @@ -174,7 +200,7 @@ this.brain.eraseMemory(MemoryModuleType.WALK_TARGET); this.brain.eraseMemory(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE); } -@@ -971,7 +1011,7 @@ +@@ -971,7 +1019,7 @@ @Override public void stopSleeping() { super.stopSleeping(); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java index 45c44c46ed..8e895d6f84 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java @@ -98,6 +98,34 @@ public class CraftVillager extends CraftAbstractVillager implements Villager { } // Paper start + @Override + public boolean increaseLevel(int amount) { + Preconditions.checkArgument(amount > 0, "Level earned must be positive"); + int supposedFinalLevel = this.getVillagerLevel() + amount; + Preconditions.checkArgument(net.minecraft.world.entity.npc.VillagerData.MIN_VILLAGER_LEVEL <= supposedFinalLevel && supposedFinalLevel <= net.minecraft.world.entity.npc.VillagerData.MAX_VILLAGER_LEVEL, + "Final level reached after the donation (%d) must be between [%d, %d]".formatted(supposedFinalLevel, net.minecraft.world.entity.npc.VillagerData.MIN_VILLAGER_LEVEL, net.minecraft.world.entity.npc.VillagerData.MAX_VILLAGER_LEVEL)); + + it.unimi.dsi.fastutil.ints.Int2ObjectMap trades = + net.minecraft.world.entity.npc.VillagerTrades.TRADES.get(this.getHandle().getVillagerData().getProfession()); + + if (trades == null || trades.isEmpty()) { + this.getHandle().setVillagerData(this.getHandle().getVillagerData().setLevel(supposedFinalLevel)); + return false; + } + + while (amount > 0) { + this.getHandle().increaseMerchantCareer(); + amount--; + } + return true; + } + + @Override + public boolean addTrades(int amount) { + Preconditions.checkArgument(amount > 0, "Number of trades unlocked must be positive"); + return this.getHandle().updateTrades(amount); + } + @Override public int getRestocksToday() { return getHandle().numberOfRestocksToday;