c97ce029e9
PaperMC believes that 1.16.2 is now ready for general release as we fixed the main issue plagueing the 1.16.x release, the MapLike data conversion issues. Until now, it was not safe for a server to convert a world to 1.16.2 without data conversion issues around villages and potentially other things. If you did, those MapLike errors meant something went wrong. This is now resolved. Big thanks to all those that helped, notably @BillyGalbreath and @Proximyst who did large parts of the update process with me. Please as always, backup your worlds and test before updating to 1.16.2! If you update to 1.16.2, there is no going back to an older build than this. --------------------------------- Co-authored-by: William Blake Galbreath <Blake.Galbreath@GMail.com> Co-authored-by: Mariell Hoversholm <proximyst@proximyst.com> Co-authored-by: krolik-exe <69214078+krolik-exe@users.noreply.github.com> Co-authored-by: BillyGalbreath <BillyGalbreath@users.noreply.github.com> Co-authored-by: stonar96 <minecraft.stonar96@gmail.com> Co-authored-by: Shane Freeder <theboyetronic@gmail.com> Co-authored-by: Jason <jasonpenilla2@me.com> Co-authored-by: kashike <kashike@vq.lc> Co-authored-by: Aurora <21148213+aurorasmiles@users.noreply.github.com> Co-authored-by: KennyTV <kennytv@t-online.de> Co-authored-by: commandblockguy <commandblockguy1@gmail.com> Co-authored-by: DigitalRegent <misterwener@gmail.com> Co-authored-by: ishland <ishlandmc@yeah.net>
149 Zeilen
6.5 KiB
Diff
149 Zeilen
6.5 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
|
|
|
|
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 4a5b54b44958b7eddaf2cd7bd517647cca96fd62..46e910581210421c8699637431804dc2f43eb4a6 100644
|
|
--- a/src/main/java/net/minecraft/server/BehaviorGate.java
|
|
+++ b/src/main/java/net/minecraft/server/BehaviorGate.java
|
|
@@ -12,7 +12,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);
|
|
@@ -60,10 +60,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
|
|
@@ -110,7 +109,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/server/WeightedList.java b/src/main/java/net/minecraft/server/WeightedList.java
|
|
index 73e5969b2a15f1639b6285286820e9f7871c7db8..5d9d58411f2fad9d5da703f964d269b4a7c2b205 100644
|
|
--- a/src/main/java/net/minecraft/server/WeightedList.java
|
|
+++ b/src/main/java/net/minecraft/server/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());
|