From 4455020aa48c03b4c143646c6013a97f027075ea Mon Sep 17 00:00:00 2001
From: Mariell <proximyst@proximyst.com>
Date: Wed, 8 Jul 2020 21:57:24 +0200
Subject: [PATCH] Fix Villagers WeightedList issue (#3860)

dont clone the list for villagers as the list is accessed post sort and needs to have sorted data.
---
 ...ix-Concurrency-issue-in-WeightedList.patch | 63 +++++++++++++++++--
 1 file changed, 58 insertions(+), 5 deletions(-)

diff --git a/Spigot-Server-Patches/Fix-Concurrency-issue-in-WeightedList.patch b/Spigot-Server-Patches/Fix-Concurrency-issue-in-WeightedList.patch
index 79e5416929..a97472a245 100644
--- a/Spigot-Server-Patches/Fix-Concurrency-issue-in-WeightedList.patch
+++ b/Spigot-Server-Patches/Fix-Concurrency-issue-in-WeightedList.patch
@@ -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
      }