-
Bug
-
Resolution: Fixed
-
1.14.4
-
Confirmed
-
Trading
The bug
Villagers do not properly keep track of the last time they restocked, neither the number of times they have restocked in the day. This causes villagers indefinitely restocking each time they visit their POI during their work hours. This happens with each villager once the world has passed a a half-day of gametime.
How to reproduce
- Let the world gametime reach at least 12,000 ticks (/time query gametime to check).
- Spawn a villager in an empty superflat world with access to a POI
- Trade with this villager during work hours
The villager will restock every time he works at his workstation, leading to the possibility of abusing his trades (MissLauralot's 2nd screenshot shows 4 stacks of emeralds obtainable in one day), even while the GUI is still open (Johnibur's video: 2019-07-23 12-11-49.mp4).
As a result of the restocks not being tracked, the demand being reduced at every restock will absurdly go down, in the wrong direction (MissLauralot's 1st screenshot, making the prices not affected by an excessive use of the same trades.
The nbt values LastRestock and RestocksToday always stay at 0.
Code analysis by Johnibur:
This method (own mappings) from the Entity Villager class performs the restocking (set trades use values to 0) and set tracking values which are used for the hasNotAlreadyRestocked() condition further below:
public void restock() { this.goSetDemand(); Iterator iterator = this.getOffers().iterator(); // Do the restock while (iterator.hasNext()) { MerchantRecipe merchantrecipe = (MerchantRecipe) iterator.next(); merchantrecipe.resetUses(); } // (…) if (this.getVillagerData().getProfession() == VillagerProfession.FARMER) { this.eE(); } // Set the tracking values this.lastRestock = this.world.getTime(); ++this.restocksToday; }
It is called each time the villager works at his workstation, provided the following requirement is met:
public boolean isRestockNeeded() { // This is for wether or not calling for demand long i = this.lastRestock + 12000L; boolean flag = this.world.getTime() > i; long j = this.world.getDayTime(); if (this.bP > 0L) { long k = this.bP / 24000L; long l = j / 24000L; flag |= l > k; } this.bP = j; if (flag) { // method preparing to set the demand } // Real conditions return this.hasNotAlreadyRestocked() && this.IsOutOfStock(); }
The method isOutOfStock() checks whether any stock has been depleted:
private boolean isOutOfSTock() { Iterator iterator = this.getOffers().iterator(); MerchantRecipe merchantrecipe; do { if (!iterator.hasNext()) { return false; // Can't find any fully used offer } merchantrecipe = (MerchantRecipe) iterator.next(); } while (!merchantrecipe.isFullyUsed()); return true; }
Yet, the restock can already be potentially done inside the method called for demand:
private void prepareforSettingDemand() { int i = 2 - this.restocksToday; // This creates the issue: restock is prematurely been made here. if (i > 0) { Iterator iterator = this.getOffers().iterator(); while (iterator.hasNext()) { MerchantRecipe merchantrecipe = (MerchantRecipe) iterator.next(); merchantrecipe.resetUses(); } } for (int j = 0; j < i; ++j) { this.setDemand(); } }
This leads to isRestockNeeded() always be false once a certain amount of gametime has passed, because the restock is already done in the call for demand methods, but not tracked at all. Thus properly restocking is not possible.
- is duplicated by
-
MC-157197 Infinite villager trading
- Resolved
-
MC-157298 Villagers Indefinitely Restocking Trades
- Resolved
-
MC-158433 Villagers restock their trades non-stop when they work in 1.14.4
- Resolved
-
MC-158851 villager trades after his trades getting locked
- Resolved
-
MC-158881 Villager refills his stock infinitely
- Resolved
-
MC-159605 Villagers can restock more than 2x a day
- Resolved
-
MC-160025 Villagers can supplementary their goods Infinite times,but don't work at afternoon
- Resolved
-
MC-160198 villagers restock trades more than 2 times a day
- Resolved
- relates to
-
MC-167002 Villagers do not reset their trades every time they work at their workstation
- Resolved