Fix Villagers WeightedList issue (#3860)

dont clone the list for villagers as the list is accessed post sort and needs to have sorted data.
This commit is contained in:
Mariell 2020-07-08 21:57:24 +02:00
parent aa9c5663ec
commit 4455020aa4

View file

@ -6,10 +6,53 @@ 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/BehaviorGate.java
+++ b/src/main/java/net/minecraft/server/BehaviorGate.java
@@ -0,0 +0,0 @@ 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);
@@ -0,0 +0,0 @@ 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
@@ -0,0 +0,0 @@ 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/server/WeightedList.java b/src/main/java/net/minecraft/server/WeightedList.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/WeightedList.java
+++ b/src/main/java/net/minecraft/server/WeightedList.java
@@ -0,0 +0,0 @@ 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;
@@ -0,0 +0,0 @@ import java.util.stream.Stream;
public class WeightedList<U> {
@ -17,11 +60,21 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- 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() {
@@ -0,0 +0,0 @@ public class WeightedList<U> {
- 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) {
+ 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
@ -53,10 +106,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- }));
- return this;
+ // Paper start - make concurrent safe, work off a clone of the list
+ java.util.ArrayList<WeightedList.a<U>> list = new java.util.ArrayList<WeightedList.a<U>>(this.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 new WeightedList<>(list);
+ return isUnsafe ? new WeightedList<>(list, isUnsafe) : this;
+ // Paper end
}