From 4455020aa48c03b4c143646c6013a97f027075ea Mon Sep 17 00:00:00 2001 From: Mariell <proximyst@proximyst.com> Date: Wed, 8 Jul 2020 21:57:24 +0200 Subject: [PATCH] Fix Villagers WeightedList issue (#3860) dont clone the list for villagers as the list is accessed post sort and needs to have sorted data. --- ...ix-Concurrency-issue-in-WeightedList.patch | 63 +++++++++++++++++-- 1 file changed, 58 insertions(+), 5 deletions(-) diff --git a/Spigot-Server-Patches/Fix-Concurrency-issue-in-WeightedList.patch b/Spigot-Server-Patches/Fix-Concurrency-issue-in-WeightedList.patch index 79e5416929..a97472a245 100644 --- a/Spigot-Server-Patches/Fix-Concurrency-issue-in-WeightedList.patch +++ b/Spigot-Server-Patches/Fix-Concurrency-issue-in-WeightedList.patch @@ -6,10 +6,53 @@ Subject: [PATCH] Fix Concurrency issue in WeightedList if multiple threads from worldgen sort at same time, it will crash. So make a copy of the list for sorting purposes. +diff --git a/src/main/java/net/minecraft/server/BehaviorGate.java b/src/main/java/net/minecraft/server/BehaviorGate.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/BehaviorGate.java ++++ b/src/main/java/net/minecraft/server/BehaviorGate.java +@@ -0,0 +0,0 @@ public class BehaviorGate<E extends EntityLiving> extends Behavior<E> { + private final Set<MemoryModuleType<?>> b; + private final BehaviorGate.Order c; + private final BehaviorGate.Execution d; +- private final WeightedList<Behavior<? super E>> e = new WeightedList<>(); ++ private final WeightedList<Behavior<? super E>> e = new WeightedList<>(false); // Paper - don't use a clone + + public BehaviorGate(Map<MemoryModuleType<?>, MemoryStatus> map, Set<MemoryModuleType<?>> set, BehaviorGate.Order behaviorgate_order, BehaviorGate.Execution behaviorgate_execution, List<Pair<Behavior<? super E>, Integer>> list) { + super(map); +@@ -0,0 +0,0 @@ public class BehaviorGate<E extends EntityLiving> extends Behavior<E> { + }).forEach((behavior) -> { + behavior.g(worldserver, e0, i); + }); +- Set set = this.b; + BehaviorController behaviorcontroller = e0.getBehaviorController(); + +- set.forEach(behaviorcontroller::removeMemory); ++ this.b.forEach(behaviorcontroller::removeMemory); // Paper - decomp fix + } + + @Override +@@ -0,0 +0,0 @@ public class BehaviorGate<E extends EntityLiving> extends Behavior<E> { + + private final Consumer<WeightedList<?>> c; + +- private Order(Consumer consumer) { ++ private Order(Consumer<WeightedList<?>> consumer) { // Paper - decomp fix + this.c = consumer; + } + diff --git a/src/main/java/net/minecraft/server/WeightedList.java b/src/main/java/net/minecraft/server/WeightedList.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/WeightedList.java +++ b/src/main/java/net/minecraft/server/WeightedList.java +@@ -0,0 +0,0 @@ import com.mojang.serialization.Codec; + import com.mojang.serialization.DataResult; + import com.mojang.serialization.Dynamic; + import com.mojang.serialization.DynamicOps; +-import com.mojang.serialization.OptionalDynamic; ++ + import java.util.Comparator; + import java.util.List; + import java.util.Random; @@ -0,0 +0,0 @@ import java.util.stream.Stream; public class WeightedList<U> { @@ -17,11 +60,21 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - protected final List<WeightedList.a<U>> a; + protected final List<WeightedList.a<U>> list; // Paper - decompile conflict private final Random b; ++ private final boolean isUnsafe; // Paper - public WeightedList() { -@@ -0,0 +0,0 @@ public class WeightedList<U> { +- public WeightedList() { +- this(Lists.newArrayList()); ++ // Paper start - add useClone option ++ public WeightedList() { this(true); } ++ public WeightedList(boolean isUnsafe) { ++ this(Lists.newArrayList(), isUnsafe); + } - private WeightedList(List<WeightedList.a<U>> list) { +- private WeightedList(List<WeightedList.a<U>> list) { ++ private WeightedList(List<WeightedList.a<U>> list) { this(list, true); } ++ private WeightedList(List<WeightedList.a<U>> list, boolean isUnsafe) { ++ this.isUnsafe = isUnsafe; ++ // Paper end this.b = new Random(); - this.a = Lists.newArrayList(list); + this.list = Lists.newArrayList(list); // Paper - decompile conflict @@ -53,10 +106,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - })); - return this; + // Paper start - make concurrent safe, work off a clone of the list -+ java.util.ArrayList<WeightedList.a<U>> list = new java.util.ArrayList<WeightedList.a<U>>(this.list); ++ List<WeightedList.a<U>> list = isUnsafe ? new java.util.ArrayList<WeightedList.a<U>>(this.list) : this.list; + list.forEach((weightedlist_a) -> weightedlist_a.a(random.nextFloat())); + list.sort(Comparator.comparingDouble(a::c)); -+ return new WeightedList<>(list); ++ return isUnsafe ? new WeightedList<>(list, isUnsafe) : this; + // Paper end }