diff --git a/paper-server/patches/sources/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java.patch b/paper-server/patches/sources/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java.patch new file mode 100644 index 0000000000..1b253028b4 --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java.patch @@ -0,0 +1,41 @@ +--- a/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java ++++ b/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java +@@ -15,32 +15,32 @@ + import net.minecraft.world.level.storage.loot.LootContext; + + public abstract class SimpleCriterionTrigger implements CriterionTrigger { +- private final Map>> players = Maps.newIdentityHashMap(); ++ // private final Map>> players = Maps.newIdentityHashMap(); // Paper - fix AdvancementDataPlayer leak; moved into AdvancementDataPlayer to fix memory leak + + @Override + public final void addPlayerListener(PlayerAdvancements manager, CriterionTrigger.Listener conditions) { +- this.players.computeIfAbsent(manager, managerx -> Sets.newHashSet()).add(conditions); ++ manager.criterionData.computeIfAbsent(this, managerx -> Sets.newHashSet()).add(conditions); // Paper - fix AdvancementDataPlayer leak + } + + @Override + public final void removePlayerListener(PlayerAdvancements manager, CriterionTrigger.Listener conditions) { +- Set> set = this.players.get(manager); ++ Set> set = (Set) manager.criterionData.get(this); // Paper - fix AdvancementDataPlayer leak + if (set != null) { + set.remove(conditions); + if (set.isEmpty()) { +- this.players.remove(manager); ++ manager.criterionData.remove(this); // Paper - fix AdvancementDataPlayer leak + } + } + } + + @Override + public final void removePlayerListeners(PlayerAdvancements tracker) { +- this.players.remove(tracker); ++ tracker.criterionData.remove(this); // Paper - fix AdvancementDataPlayer leak + } + + protected void trigger(ServerPlayer player, Predicate predicate) { + PlayerAdvancements playerAdvancements = player.getAdvancements(); +- Set> set = this.players.get(playerAdvancements); ++ Set> set = (Set) playerAdvancements.criterionData.get(this); // Paper - fix AdvancementDataPlayer leak + if (set != null && !set.isEmpty()) { + LootContext lootContext = EntityPredicate.createContext(player, player); + List> list = null; diff --git a/paper-server/patches/sources/net/minecraft/server/PlayerAdvancements.java.patch b/paper-server/patches/sources/net/minecraft/server/PlayerAdvancements.java.patch index 74ffb0eec1..999b47b909 100644 --- a/paper-server/patches/sources/net/minecraft/server/PlayerAdvancements.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/PlayerAdvancements.java.patch @@ -1,6 +1,14 @@ --- a/net/minecraft/server/PlayerAdvancements.java +++ b/net/minecraft/server/PlayerAdvancements.java -@@ -162,6 +162,7 @@ +@@ -63,6 +63,7 @@ + private AdvancementHolder lastSelectedTab; + private boolean isFirstPacket = true; + private final Codec codec; ++ public final Map, Set>> criterionData = new java.util.IdentityHashMap<>(); // Paper - fix advancement data player leakage + + public PlayerAdvancements(DataFixer dataFixer, PlayerList playerManager, ServerAdvancementManager advancementLoader, Path filePath, ServerPlayer owner) { + this.playerList = playerManager; +@@ -162,6 +163,7 @@ } public void save() { @@ -8,7 +16,7 @@ JsonElement jsonelement = (JsonElement) this.codec.encodeStart(JsonOps.INSTANCE, this.asData()).getOrThrow(); try { -@@ -196,6 +197,7 @@ +@@ -196,6 +198,7 @@ AdvancementHolder advancementholder = loader.get(minecraftkey); if (advancementholder == null) { @@ -16,7 +24,7 @@ PlayerAdvancements.LOGGER.warn("Ignored advancement '{}' in progress file {} - it doesn't exist anymore?", minecraftkey, this.playerSavePath); } else { this.startProgress(advancementholder, advancementprogress); -@@ -223,10 +225,17 @@ +@@ -223,10 +226,17 @@ boolean flag1 = advancementprogress.isDone(); if (advancementprogress.grantProgress(criterionName)) {