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. if multiple threads from worldgen sort at same time, it will crash.
So make a copy of the list for sorting purposes. 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 diff --git a/src/main/java/net/minecraft/server/WeightedList.java b/src/main/java/net/minecraft/server/WeightedList.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/WeightedList.java --- a/src/main/java/net/minecraft/server/WeightedList.java
+++ b/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; @@ -0,0 +0,0 @@ import java.util.stream.Stream;
public class WeightedList<U> { public class WeightedList<U> {
@@ -17,11 +60,21 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- protected final List<WeightedList.a<U>> a; - protected final List<WeightedList.a<U>> a;
+ protected final List<WeightedList.a<U>> list; // Paper - decompile conflict + protected final List<WeightedList.a<U>> list; // Paper - decompile conflict
private final Random b; private final Random b;
+ private final boolean isUnsafe; // Paper
public WeightedList() { - public WeightedList() {
@@ -0,0 +0,0 @@ public class WeightedList<U> { - 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.b = new Random();
- this.a = Lists.newArrayList(list); - this.a = Lists.newArrayList(list);
+ this.list = Lists.newArrayList(list); // Paper - decompile conflict + this.list = Lists.newArrayList(list); // Paper - decompile conflict
@@ -53,10 +106,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- })); - }));
- return this; - return this;
+ // Paper start - make concurrent safe, work off a clone of the list + // 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.forEach((weightedlist_a) -> weightedlist_a.a(random.nextFloat()));
+ list.sort(Comparator.comparingDouble(a::c)); + list.sort(Comparator.comparingDouble(a::c));
+ return new WeightedList<>(list); + return isUnsafe ? new WeightedList<>(list, isUnsafe) : this;
+ // Paper end + // Paper end
} }