Paper/patches/removed/1.17/0528-Fix-Concurrency-issue-in-WeightedList.patch
2021-06-14 12:13:08 +02:00

154 lines
7.4 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Mon, 6 Jul 2020 18:36:41 -0400
Subject: [PATCH] Fix Concurrency issue in WeightedList
1.17 Update: Looks like whatever this patch is trying to fix might be already fixed upstream, needs to be investigated
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 0a65e442ddc31c06f3bb0ff5aa152daee7a210af..a81ad258b39b7472312ab1bedeeacaf26ffae4f7 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<E extends LivingEntity> extends Behavior<E> {
private final Set<MemoryModuleType<?>> exitErasedMemories;
private final GateBehavior.OrderPolicy orderPolicy;
private final GateBehavior.RunningPolicy runningPolicy;
- private final WeightedList<Behavior<? super E>> behaviors = new WeightedList<>();
+ private final WeightedList<Behavior<? super E>> behaviors = new WeightedList<>(false); // Paper - don't use a clone
public GateBehavior(Map<MemoryModuleType<?>, MemoryStatus> requiredMemoryState, Set<MemoryModuleType<?>> memoriesToForgetWhenStopped, GateBehavior.OrderPolicy order, GateBehavior.RunningPolicy runMode, List<Pair<Behavior<? super E>, Integer>> tasks) {
super(requiredMemoryState);
@@ -65,10 +65,9 @@ public class GateBehavior<E extends LivingEntity> extends Behavior<E> {
}).forEach((behavior) -> {
behavior.g(world, entity, time);
});
- Set set = this.exitErasedMemories;
Brain behaviorcontroller = entity.getBrain();
- set.forEach(behaviorcontroller::removeMemory);
+ this.exitErasedMemories.forEach(behaviorcontroller::eraseMemory); // Paper - decomp fix
}
@Override
@@ -111,11 +110,11 @@ public class GateBehavior<E extends LivingEntity> extends Behavior<E> {
static enum OrderPolicy {
ORDERED((weightedlist) -> {
- }), SHUFFLED(WeightedList::a);
+ }), SHUFFLED(WeightedList::shuffle);
private final Consumer<WeightedList<?>> consumer;
- private OrderPolicy(Consumer consumer) {
+ private OrderPolicy(Consumer<WeightedList<?>> consumer) { // Paper - decomp fix
this.consumer = 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 e4c1c58e9a9c744c7ebb9948a27766b84a081b9e..85df30ef7c03c2f8ae741a8cac8bf601490d2539 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.WeightedEntry<U>> entries;
+ protected final List<WeightedList.WeightedEntry<U>> list; // Paper - decompile conflict
private final Random random;
+ 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.WeightedEntry<U>> entries) {
+ private WeightedList(List<WeightedList.WeightedEntry<U>> entries) { this(entries, true); }
+ private WeightedList(List<WeightedList.WeightedEntry<U>> list, boolean isUnsafe) {
+ this.isUnsafe = isUnsafe;
+ // Paper end
this.random = new Random();
- this.entries = Lists.newArrayList(entries);
+ this.list = Lists.newArrayList(list); // Paper - decompile conflict
}
public static <U> Codec<WeightedList<U>> codec(Codec<U> codec) {
- return WeightedList.entries.a(codec).listOf().xmap(WeightedList::new, (weightedlist) -> {
- return weightedlist.a;
+ return WeightedList.WeightedEntry.codec(codec).listOf().xmap(WeightedList::new, (weightedlist) -> { // Paper - decompile conflict
+ return weightedlist.list; // Paper - decompile conflict
});
}
public WeightedList<U> add(U item, int weight) {
- this.entries.add(new WeightedList.WeightedEntry<>(item, weight));
+ this.list.add(new WeightedList.WeightedEntry<>(item, weight)); // Paper - decompile conflict
return this;
}
@@ -42,21 +48,20 @@ public class WeightedList<U> {
}
public WeightedList<U> shuffle(Random random) {
- this.entries.forEach((weightedlist_a) -> {
- weightedlist_a.setRandom(random.nextFloat());
- });
- this.entries.sort(Comparator.comparingDouble((object) -> {
- return ((WeightedList.WeightedEntry) object).getRandWeight();
- }));
- return this;
+ // Paper start - make concurrent safe, work off a clone of the list
+ List<WeightedList.WeightedEntry<U>> list = isUnsafe ? new java.util.ArrayList<WeightedList.WeightedEntry<U>>(this.list) : this.list;
+ list.forEach((weightedlist_a) -> weightedlist_a.setRandom(random.nextFloat()));
+ list.sort(Comparator.comparingDouble(WeightedEntry::getRandWeight));
+ return isUnsafe ? new WeightedList<>(list, isUnsafe) : this;
+ // Paper end
}
public boolean isEmpty() {
- return this.entries.isEmpty();
+ return this.list.isEmpty(); // Paper - decompile conflict
}
public Stream<U> stream() {
- return this.entries.stream().map(WeightedList.entries::a);
+ return this.list.stream().map(WeightedList.WeightedEntry::getData); // Paper - decompile conflict
}
public U getOne(Random random) {
@@ -64,7 +69,7 @@ public class WeightedList<U> {
}
public String toString() {
- return "WeightedList[" + this.entries + "]";
+ return "WeightedList[" + this.list + "]"; // Paper - decompile conflict
}
public static class WeightedEntry<T> {
@@ -98,11 +103,7 @@ public class WeightedList<U> {
return new Codec<WeightedList.WeightedEntry<E>>() {
public <T> DataResult<Pair<WeightedList.WeightedEntry<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.WeightedEntry<>(object, dynamic.get("weight").asInt(1));
}).map((weightedlist_a) -> {
return Pair.of(weightedlist_a, dynamicops.empty());