From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Aikar Date: Mon, 6 Jul 2020 18:36:41 -0400 Subject: [PATCH] Fix Concurrency issue in ShufflingList 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/GateBehavior.java b/src/main/java/net/minecraft/world/entity/ai/behavior/GateBehavior.java index 419eadbe31b86b7192fd7a63268d547705e7c7ce..b45c4f50705f80163d44d9e588f86a5770f5be38 100644 --- a/src/main/java/net/minecraft/world/entity/ai/behavior/GateBehavior.java +++ b/src/main/java/net/minecraft/world/entity/ai/behavior/GateBehavior.java @@ -17,7 +17,7 @@ public class GateBehavior implements BehaviorControl private final Set> exitErasedMemories; private final GateBehavior.OrderPolicy orderPolicy; private final GateBehavior.RunningPolicy runningPolicy; - private final ShufflingList> behaviors = new ShufflingList<>(); + private final ShufflingList> behaviors = new ShufflingList<>(false); // Paper - don't use a clone private Behavior.Status status = Behavior.Status.STOPPED; public GateBehavior(Map, MemoryStatus> requiredMemoryState, Set> memoriesToForgetWhenStopped, GateBehavior.OrderPolicy order, GateBehavior.RunningPolicy runMode, List, Integer>> tasks) { diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/ShufflingList.java b/src/main/java/net/minecraft/world/entity/ai/behavior/ShufflingList.java index 9fb20cd00568aeea25284ea0e80fe52cb1c3eede..731ef21dbbd25d6924717de42f4569a9b5935643 100644 --- a/src/main/java/net/minecraft/world/entity/ai/behavior/ShufflingList.java +++ b/src/main/java/net/minecraft/world/entity/ai/behavior/ShufflingList.java @@ -16,12 +16,25 @@ import net.minecraft.util.RandomSource; public class ShufflingList implements Iterable { protected final List> entries; private final RandomSource random = RandomSource.create(); + private final boolean isUnsafe; // Paper public ShufflingList() { + // Paper start + this(true); + } + public ShufflingList(boolean isUnsafe) { + this.isUnsafe = isUnsafe; + // Paper end this.entries = Lists.newArrayList(); } private ShufflingList(List> list) { + // Paper start + this(list, true); + } + private ShufflingList(List> list, boolean isUnsafe) { + this.isUnsafe = isUnsafe; + // Paper end this.entries = Lists.newArrayList(list); } @@ -37,11 +50,12 @@ public class ShufflingList implements Iterable { } public ShufflingList shuffle() { - this.entries.forEach((entry) -> { - entry.setRandom(this.random.nextFloat()); - }); - this.entries.sort(Comparator.comparingDouble(ShufflingList.WeightedEntry::getRandWeight)); - return this; + // Paper start - make concurrent safe, work off a clone of the list + List> list = this.isUnsafe ? Lists.newArrayList(this.entries) : this.entries; + list.forEach(entry -> entry.setRandom(this.random.nextFloat())); + list.sort(Comparator.comparingDouble(ShufflingList.WeightedEntry::getRandWeight)); + return this.isUnsafe ? new ShufflingList<>(list, this.isUnsafe) : this; + // Paper end } public Stream stream() {