aboutsummaryrefslogtreecommitdiffhomepage
path: root/Spigot-Server-Patches-Unmapped/0528-Fix-Concurrency-issue-in-WeightedList.patch
diff options
context:
space:
mode:
Diffstat (limited to 'Spigot-Server-Patches-Unmapped/0528-Fix-Concurrency-issue-in-WeightedList.patch')
-rw-r--r--Spigot-Server-Patches-Unmapped/0528-Fix-Concurrency-issue-in-WeightedList.patch148
1 files changed, 148 insertions, 0 deletions
diff --git a/Spigot-Server-Patches-Unmapped/0528-Fix-Concurrency-issue-in-WeightedList.patch b/Spigot-Server-Patches-Unmapped/0528-Fix-Concurrency-issue-in-WeightedList.patch
new file mode 100644
index 0000000000..9a961b6d30
--- /dev/null
+++ b/Spigot-Server-Patches-Unmapped/0528-Fix-Concurrency-issue-in-WeightedList.patch
@@ -0,0 +1,148 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Aikar <[email protected]>
+Date: Mon, 6 Jul 2020 18:36:41 -0400
+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/world/entity/ai/behavior/BehaviorGate.java b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorGate.java
+index dc926f7e59fa350902d4a24aefc3df3eac7d75db..2d4345de154fb2d31f34695672ebdb4dac31b181 100644
+--- a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorGate.java
++++ b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorGate.java
+@@ -17,7 +17,7 @@ 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);
+@@ -65,10 +65,9 @@ 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
+@@ -115,7 +114,7 @@ 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/world/entity/ai/behavior/WeightedList.java b/src/main/java/net/minecraft/world/entity/ai/behavior/WeightedList.java
+index f6f8c68ff3642e28901094e8b501fcf8ec2cecd7..1ca9b0595ae9d914d23590ec0b0c2e857c39b250 100644
+--- a/src/main/java/net/minecraft/world/entity/ai/behavior/WeightedList.java
++++ b/src/main/java/net/minecraft/world/entity/ai/behavior/WeightedList.java
+@@ -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<U> {
+
+- 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() {
+- 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) { 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
+ }
+
+ public static <U> Codec<WeightedList<U>> a(Codec<U> codec) {
+- return WeightedList.a.a(codec).listOf().xmap(WeightedList::new, (weightedlist) -> {
+- return weightedlist.a;
++ return WeightedList.a.a(codec).listOf().xmap(WeightedList::new, (weightedlist) -> { // Paper - decompile conflict
++ return weightedlist.list; // Paper - decompile conflict
+ });
+ }
+
+ public WeightedList<U> a(U u0, int i) {
+- this.a.add(new WeightedList.a<>(u0, i));
++ this.list.add(new WeightedList.a<>(u0, i)); // Paper - decompile conflict
+ return this;
+ }
+
+@@ -42,21 +48,20 @@ public class WeightedList<U> {
+ }
+
+ public WeightedList<U> a(Random random) {
+- this.a.forEach((weightedlist_a) -> {
+- weightedlist_a.a(random.nextFloat());
+- });
+- this.a.sort(Comparator.comparingDouble((object) -> {
+- return ((WeightedList.a) object).c();
+- }));
+- return this;
++ // Paper start - make concurrent safe, work off a clone of the 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 isUnsafe ? new WeightedList<>(list, isUnsafe) : this;
++ // Paper end
+ }
+
+ public boolean b() {
+- return this.a.isEmpty();
++ return this.list.isEmpty(); // Paper - decompile conflict
+ }
+
+ public Stream<U> c() {
+- return this.a.stream().map(WeightedList.a::a);
++ return this.list.stream().map(WeightedList.a::a); // Paper - decompile conflict
+ }
+
+ public U b(Random random) {
+@@ -64,7 +69,7 @@ public class WeightedList<U> {
+ }
+
+ public String toString() {
+- return "WeightedList[" + this.a + "]";
++ return "WeightedList[" + this.list + "]"; // Paper - decompile conflict
+ }
+
+ public static class a<T> {
+@@ -98,11 +103,7 @@ public class WeightedList<U> {
+ return new Codec<WeightedList.a<E>>() {
+ public <T> DataResult<Pair<WeightedList.a<E>, T>> decode(DynamicOps<T> dynamicops, T t0) {
+ Dynamic<T> dynamic = new Dynamic(dynamicops, t0);
+- OptionalDynamic optionaldynamic = dynamic.get("data");
+- Codec codec1 = codec;
+-
+- codec.getClass();
+- return optionaldynamic.flatMap(codec1::parse).map((object) -> {
++ return dynamic.get("data").flatMap(codec::parse).map((object) -> { // Paper - decompile error
+ return new WeightedList.a<>(object, dynamic.get("weight").asInt(1));
+ }).map((weightedlist_a) -> {
+ return Pair.of(weightedlist_a, dynamicops.empty());