mirror of
https://github.com/PaperMC/Paper.git
synced 2025-01-06 00:07:56 +01:00
5f134afc4b
For each player on each tick, enter block triggers are invoked, and these create loot contexts that are promptly thrown away since the trigger doesn't pass the predicate To avoid this, we now lazily create the LootContext if the criterion passes the predicate AND if any of the listener triggers require a loot context instance
53 lines
3.3 KiB
Diff
53 lines
3.3 KiB
Diff
--- a/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java
|
|
+++ b/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java
|
|
@@ -15,41 +15,41 @@
|
|
import net.minecraft.world.level.storage.loot.LootContext;
|
|
|
|
public abstract class SimpleCriterionTrigger<T extends SimpleCriterionTrigger.SimpleInstance> implements CriterionTrigger<T> {
|
|
- private final Map<PlayerAdvancements, Set<CriterionTrigger.Listener<T>>> players = Maps.newIdentityHashMap();
|
|
+ // private final Map<PlayerAdvancements, Set<CriterionTrigger.Listener<T>>> players = Maps.newIdentityHashMap(); // Paper - fix AdvancementDataPlayer leak; moved into AdvancementDataPlayer to fix memory leak
|
|
|
|
@Override
|
|
public final void addPlayerListener(PlayerAdvancements manager, CriterionTrigger.Listener<T> 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<T> conditions) {
|
|
- Set<CriterionTrigger.Listener<T>> set = this.players.get(manager);
|
|
+ Set<CriterionTrigger.Listener<T>> 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<T> predicate) {
|
|
PlayerAdvancements playerAdvancements = player.getAdvancements();
|
|
- Set<CriterionTrigger.Listener<T>> set = this.players.get(playerAdvancements);
|
|
+ Set<CriterionTrigger.Listener<T>> set = (Set) playerAdvancements.criterionData.get(this); // Paper - fix AdvancementDataPlayer leak
|
|
if (set != null && !set.isEmpty()) {
|
|
- LootContext lootContext = EntityPredicate.createContext(player, player);
|
|
+ LootContext lootContext = null; // EntityPredicate.createContext(player, player); // Paper - Perf: lazily create LootContext for criterions
|
|
List<CriterionTrigger.Listener<T>> list = null;
|
|
|
|
for (CriterionTrigger.Listener<T> listener : set) {
|
|
T simpleInstance = listener.trigger();
|
|
if (predicate.test(simpleInstance)) {
|
|
Optional<ContextAwarePredicate> optional = simpleInstance.player();
|
|
- if (optional.isEmpty() || optional.get().matches(lootContext)) {
|
|
+ if (optional.isEmpty() || optional.get().matches(lootContext = (lootContext == null ? EntityPredicate.createContext(player, player) : lootContext))) { // Paper - Perf: lazily create LootContext for criterions
|
|
if (list == null) {
|
|
list = Lists.newArrayList();
|
|
}
|