diff options
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.patch | 148 |
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()); |