diff --git a/Spigot-Server-Patches/0540-Fix-Concurrency-issue-in-WeightedList.patch b/Spigot-Server-Patches/0540-Fix-Concurrency-issue-in-WeightedList.patch index 7279b4f888..2714f9eaeb 100644 --- a/Spigot-Server-Patches/0540-Fix-Concurrency-issue-in-WeightedList.patch +++ b/Spigot-Server-Patches/0540-Fix-Concurrency-issue-in-WeightedList.patch @@ -6,22 +6,75 @@ 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 4a5b54b44958b7eddaf2cd7bd517647cca96fd62..46e910581210421c8699637431804dc2f43eb4a6 100644 +--- a/src/main/java/net/minecraft/server/BehaviorGate.java ++++ b/src/main/java/net/minecraft/server/BehaviorGate.java +@@ -12,7 +12,7 @@ public class BehaviorGate extends Behavior { + private final Set> b; + private final BehaviorGate.Order c; + private final BehaviorGate.Execution d; +- private final WeightedList> e = new WeightedList<>(); ++ private final WeightedList> e = new WeightedList<>(false); // Paper - don't use a clone + + public BehaviorGate(Map, MemoryStatus> map, Set> set, BehaviorGate.Order behaviorgate_order, BehaviorGate.Execution behaviorgate_execution, List, Integer>> list) { + super(map); +@@ -60,10 +60,9 @@ public class BehaviorGate extends Behavior { + }).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 +@@ -110,7 +109,7 @@ public class BehaviorGate extends Behavior { + + private final Consumer> c; + +- private Order(Consumer consumer) { ++ private Order(Consumer> 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 73e5969b2a15f1639b6285286820e9f7871c7db8..b4e871140e7a0ab5e402e415ea4ff04605157d54 100644 +index 73e5969b2a15f1639b6285286820e9f7871c7db8..5d9d58411f2fad9d5da703f964d269b4a7c2b205 100644 --- a/src/main/java/net/minecraft/server/WeightedList.java +++ b/src/main/java/net/minecraft/server/WeightedList.java -@@ -14,7 +14,7 @@ import java.util.stream.Stream; +@@ -6,7 +6,7 @@ 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; +@@ -14,26 +14,32 @@ import java.util.stream.Stream; public class WeightedList { - protected final List> a; + protected final List> list; // Paper - decompile conflict private final Random b; ++ private final boolean isUnsafe; // Paper - public WeightedList() { -@@ -23,17 +23,17 @@ public class WeightedList { +- 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> list) { +- private WeightedList(List> list) { ++ private WeightedList(List> list) { this(list, true); } ++ private WeightedList(List> 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 @@ -41,7 +94,7 @@ index 73e5969b2a15f1639b6285286820e9f7871c7db8..b4e871140e7a0ab5e402e415ea4ff046 return this; } -@@ -42,21 +42,20 @@ public class WeightedList { +@@ -42,21 +48,20 @@ public class WeightedList { } public WeightedList a(Random random) { @@ -53,10 +106,10 @@ index 73e5969b2a15f1639b6285286820e9f7871c7db8..b4e871140e7a0ab5e402e415ea4ff046 - })); - return this; + // Paper start - make concurrent safe, work off a clone of the list -+ java.util.ArrayList> list = new java.util.ArrayList>(this.list); ++ List> list = isUnsafe ? new java.util.ArrayList>(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 } @@ -71,7 +124,7 @@ index 73e5969b2a15f1639b6285286820e9f7871c7db8..b4e871140e7a0ab5e402e415ea4ff046 } public U b(Random random) { -@@ -64,7 +63,7 @@ public class WeightedList { +@@ -64,7 +69,7 @@ public class WeightedList { } public String toString() { @@ -80,7 +133,7 @@ index 73e5969b2a15f1639b6285286820e9f7871c7db8..b4e871140e7a0ab5e402e415ea4ff046 } public static class a { -@@ -98,11 +97,7 @@ public class WeightedList { +@@ -98,11 +103,7 @@ public class WeightedList { return new Codec>() { public DataResult, T>> decode(DynamicOps dynamicops, T t0) { Dynamic dynamic = new Dynamic(dynamicops, t0);