--- a/net/minecraft/advancements/Advancement.java
+++ b/net/minecraft/advancements/Advancement.java
@@ -7,7 +7,9 @@
 import com.google.gson.JsonObject;
 import com.google.gson.JsonSyntaxException;
 import java.util.Arrays;
+import java.util.Iterator;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Set;
 import java.util.function.Consumer;
 import java.util.function.Function;
@@ -18,6 +20,7 @@
 import net.minecraft.network.chat.Component;
 import net.minecraft.network.chat.ComponentUtils;
 import net.minecraft.network.chat.HoverEvent;
+import net.minecraft.network.chat.MutableComponent;
 import net.minecraft.network.chat.Style;
 import net.minecraft.resources.ResourceLocation;
 import net.minecraft.util.GsonHelper;
@@ -26,6 +29,7 @@
 import org.apache.commons.lang3.ArrayUtils;
 
 public class Advancement {
+
     @Nullable
     private final Advancement parent;
     @Nullable
@@ -36,6 +40,7 @@
     private final String[][] requirements;
     private final Set<Advancement> children = Sets.newLinkedHashSet();
     private final Component chatComponent;
+    public final org.bukkit.advancement.Advancement bukkit = new org.bukkit.craftbukkit.v1_19_R1.advancement.CraftAdvancement(this); // CraftBukkit
 
     public Advancement(ResourceLocation id, @Nullable Advancement parent, @Nullable DisplayInfo display, AdvancementRewards rewards, Map<String, Criterion> criteria, String[][] requirements) {
         this.id = id;
@@ -48,16 +53,25 @@
             parent.addChild(this);
         }
 
-        if (display == null) {
-            this.chatComponent = Component.literal(id.toString());
+        // Paper start - moved to static method
+        this.chatComponent = constructDisplayComponent(this.id, this.display);
+    }
+
+    public static Component constructDisplayComponent(final @Nullable ResourceLocation id, final @Nullable DisplayInfo display) {
+        if (id == null && display == null) {
+            throw new IllegalArgumentException("can't both be null");
+        } else if (display == null) {
+            return Component.literal(id.toString());
+        // Paper end
         } else {
-            Component component = display.getTitle();
-            ChatFormatting chatFormatting = display.getFrame().getChatColor();
-            Component component2 = ComponentUtils.mergeStyles(component.copy(), Style.EMPTY.withColor(chatFormatting)).append("\n").append(display.getDescription());
-            Component component3 = component.copy().withStyle((style) -> {
-                return style.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, component2));
+            Component ichatbasecomponent = display.getTitle();
+            ChatFormatting enumchatformat = display.getFrame().getChatColor();
+            MutableComponent ichatmutablecomponent = ComponentUtils.mergeStyles(ichatbasecomponent.copy(), Style.EMPTY.withColor(enumchatformat)).append("\n").append(display.getDescription());
+            MutableComponent ichatmutablecomponent1 = ichatbasecomponent.copy().withStyle((chatmodifier) -> {
+                return chatmodifier.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, ichatmutablecomponent));
             });
-            this.chatComponent = ComponentUtils.wrapInSquareBrackets(component3).withStyle(chatFormatting);
+
+            return ComponentUtils.wrapInSquareBrackets(ichatmutablecomponent1).withStyle(enumchatformat); // Paper
         }
 
     }
@@ -80,9 +94,10 @@
         return this.rewards;
     }
 
-    @Override
     public String toString() {
-        return "SimpleAdvancement{id=" + this.getId() + ", parent=" + (this.parent == null ? "null" : this.parent.getId()) + ", display=" + this.display + ", rewards=" + this.rewards + ", criteria=" + this.criteria + ", requirements=" + Arrays.deepToString(this.requirements) + "}";
+        ResourceLocation minecraftkey = this.getId();
+
+        return "SimpleAdvancement{id=" + minecraftkey + ", parent=" + (this.parent == null ? "null" : this.parent.getId()) + ", display=" + this.display + ", rewards=" + this.rewards + ", criteria=" + this.criteria + ", requirements=" + Arrays.deepToString(this.requirements) + "}";
     }
 
     public Iterable<Advancement> getChildren() {
@@ -105,19 +120,18 @@
         return this.id;
     }
 
-    @Override
     public boolean equals(Object object) {
         if (this == object) {
             return true;
         } else if (!(object instanceof Advancement)) {
             return false;
         } else {
-            Advancement advancement = (Advancement)object;
+            Advancement advancement = (Advancement) object;
+
             return this.id.equals(advancement.id);
         }
     }
 
-    @Override
     public int hashCode() {
         return this.id.hashCode();
     }
@@ -131,19 +145,23 @@
     }
 
     public static class Builder {
+
         @Nullable
         private ResourceLocation parentId;
         @Nullable
         private Advancement parent;
         @Nullable
         private DisplayInfo display;
-        private AdvancementRewards rewards = AdvancementRewards.EMPTY;
-        private Map<String, Criterion> criteria = Maps.newLinkedHashMap();
+        private AdvancementRewards rewards;
+        private Map<String, Criterion> criteria;
         @Nullable
         private String[][] requirements;
-        private RequirementsStrategy requirementsStrategy = RequirementsStrategy.AND;
+        private RequirementsStrategy requirementsStrategy;
 
         Builder(@Nullable ResourceLocation parentId, @Nullable DisplayInfo display, AdvancementRewards rewards, Map<String, Criterion> criteria, String[][] requirements) {
+            this.rewards = AdvancementRewards.EMPTY;
+            this.criteria = Maps.newLinkedHashMap();
+            this.requirementsStrategy = RequirementsStrategy.AND;
             this.parentId = parentId;
             this.display = display;
             this.rewards = rewards;
@@ -152,6 +170,9 @@
         }
 
         private Builder() {
+            this.rewards = AdvancementRewards.EMPTY;
+            this.criteria = Maps.newLinkedHashMap();
+            this.requirementsStrategy = RequirementsStrategy.AND;
         }
 
         public static Advancement.Builder advancement() {
@@ -218,7 +239,7 @@
                 return true;
             } else {
                 if (this.parent == null) {
-                    this.parent = parentProvider.apply(this.parentId);
+                    this.parent = (Advancement) parentProvider.apply(this.parentId);
                 }
 
                 return this.parent != null;
@@ -226,7 +247,7 @@
         }
 
         public Advancement build(ResourceLocation id) {
-            if (!this.canBuild((idx) -> {
+            if (!this.canBuild((minecraftkey1) -> {
                 return null;
             })) {
                 throw new IllegalStateException("Tried to build incomplete advancement!");
@@ -241,6 +262,7 @@
 
         public Advancement save(Consumer<Advancement> exporter, String id) {
             Advancement advancement = this.build(new ResourceLocation(id));
+
             exporter.accept(advancement);
             return advancement;
         }
@@ -250,39 +272,50 @@
                 this.requirements = this.requirementsStrategy.createRequirements(this.criteria.keySet());
             }
 
-            JsonObject jsonObject = new JsonObject();
+            JsonObject jsonobject = new JsonObject();
+
             if (this.parent != null) {
-                jsonObject.addProperty("parent", this.parent.getId().toString());
+                jsonobject.addProperty("parent", this.parent.getId().toString());
             } else if (this.parentId != null) {
-                jsonObject.addProperty("parent", this.parentId.toString());
+                jsonobject.addProperty("parent", this.parentId.toString());
             }
 
             if (this.display != null) {
-                jsonObject.add("display", this.display.serializeToJson());
+                jsonobject.add("display", this.display.serializeToJson());
             }
 
-            jsonObject.add("rewards", this.rewards.serializeToJson());
-            JsonObject jsonObject2 = new JsonObject();
+            jsonobject.add("rewards", this.rewards.serializeToJson());
+            JsonObject jsonobject1 = new JsonObject();
+            Iterator iterator = this.criteria.entrySet().iterator();
 
-            for(Map.Entry<String, Criterion> entry : this.criteria.entrySet()) {
-                jsonObject2.add(entry.getKey(), entry.getValue().serializeToJson());
+            while (iterator.hasNext()) {
+                Entry<String, Criterion> entry = (Entry) iterator.next();
+
+                jsonobject1.add((String) entry.getKey(), ((Criterion) entry.getValue()).serializeToJson());
             }
 
-            jsonObject.add("criteria", jsonObject2);
-            JsonArray jsonArray = new JsonArray();
+            jsonobject.add("criteria", jsonobject1);
+            JsonArray jsonarray = new JsonArray();
+            String[][] astring = this.requirements;
+            int i = astring.length;
 
-            for(String[] strings : this.requirements) {
-                JsonArray jsonArray2 = new JsonArray();
+            for (int j = 0; j < i; ++j) {
+                String[] astring1 = astring[j];
+                JsonArray jsonarray1 = new JsonArray();
+                String[] astring2 = astring1;
+                int k = astring1.length;
 
-                for(String string : strings) {
-                    jsonArray2.add(string);
+                for (int l = 0; l < k; ++l) {
+                    String s = astring2[l];
+
+                    jsonarray1.add(s);
                 }
 
-                jsonArray.add(jsonArray2);
+                jsonarray.add(jsonarray1);
             }
 
-            jsonObject.add("requirements", jsonArray);
-            return jsonObject;
+            jsonobject.add("requirements", jsonarray);
+            return jsonobject;
         }
 
         public void serializeToNetwork(FriendlyByteBuf buf) {
@@ -291,102 +324,143 @@
             }
 
             buf.writeNullable(this.parentId, FriendlyByteBuf::writeResourceLocation);
-            buf.writeNullable(this.display, (buf2, display) -> {
-                display.serializeToNetwork(buf2);
+            buf.writeNullable(this.display, (packetdataserializer1, advancementdisplay) -> {
+                advancementdisplay.serializeToNetwork(packetdataserializer1);
             });
             Criterion.serializeToNetwork(this.criteria, buf);
             buf.writeVarInt(this.requirements.length);
+            String[][] astring = this.requirements;
+            int i = astring.length;
 
-            for(String[] strings : this.requirements) {
-                buf.writeVarInt(strings.length);
+            for (int j = 0; j < i; ++j) {
+                String[] astring1 = astring[j];
 
-                for(String string : strings) {
-                    buf.writeUtf(string);
+                buf.writeVarInt(astring1.length);
+                String[] astring2 = astring1;
+                int k = astring1.length;
+
+                for (int l = 0; l < k; ++l) {
+                    String s = astring2[l];
+
+                    buf.writeUtf(s);
                 }
             }
 
         }
 
-        @Override
         public String toString() {
             return "Task Advancement{parentId=" + this.parentId + ", display=" + this.display + ", rewards=" + this.rewards + ", criteria=" + this.criteria + ", requirements=" + Arrays.deepToString(this.requirements) + "}";
         }
 
         public static Advancement.Builder fromJson(JsonObject obj, DeserializationContext predicateDeserializer) {
-            ResourceLocation resourceLocation = obj.has("parent") ? new ResourceLocation(GsonHelper.getAsString(obj, "parent")) : null;
-            DisplayInfo displayInfo = obj.has("display") ? DisplayInfo.fromJson(GsonHelper.getAsJsonObject(obj, "display")) : null;
-            AdvancementRewards advancementRewards = obj.has("rewards") ? AdvancementRewards.deserialize(GsonHelper.getAsJsonObject(obj, "rewards")) : AdvancementRewards.EMPTY;
+            ResourceLocation minecraftkey = obj.has("parent") ? new ResourceLocation(GsonHelper.getAsString(obj, "parent")) : null;
+            DisplayInfo advancementdisplay = obj.has("display") ? DisplayInfo.fromJson(GsonHelper.getAsJsonObject(obj, "display")) : null;
+            AdvancementRewards advancementrewards = obj.has("rewards") ? AdvancementRewards.deserialize(GsonHelper.getAsJsonObject(obj, "rewards")) : AdvancementRewards.EMPTY;
             Map<String, Criterion> map = Criterion.criteriaFromJson(GsonHelper.getAsJsonObject(obj, "criteria"), predicateDeserializer);
+
             if (map.isEmpty()) {
                 throw new JsonSyntaxException("Advancement criteria cannot be empty");
             } else {
-                JsonArray jsonArray = GsonHelper.getAsJsonArray(obj, "requirements", new JsonArray());
-                String[][] strings = new String[jsonArray.size()][];
+                JsonArray jsonarray = GsonHelper.getAsJsonArray(obj, "requirements", new JsonArray());
+                String[][] astring = new String[jsonarray.size()][];
 
-                for(int i = 0; i < jsonArray.size(); ++i) {
-                    JsonArray jsonArray2 = GsonHelper.convertToJsonArray(jsonArray.get(i), "requirements[" + i + "]");
-                    strings[i] = new String[jsonArray2.size()];
+                int i;
+                int j;
 
-                    for(int j = 0; j < jsonArray2.size(); ++j) {
-                        strings[i][j] = GsonHelper.convertToString(jsonArray2.get(j), "requirements[" + i + "][" + j + "]");
+                for (i = 0; i < jsonarray.size(); ++i) {
+                    JsonArray jsonarray1 = GsonHelper.convertToJsonArray(jsonarray.get(i), "requirements[" + i + "]");
+
+                    astring[i] = new String[jsonarray1.size()];
+
+                    for (j = 0; j < jsonarray1.size(); ++j) {
+                        astring[i][j] = GsonHelper.convertToString(jsonarray1.get(j), "requirements[" + i + "][" + j + "]");
                     }
                 }
 
-                if (strings.length == 0) {
-                    strings = new String[map.size()][];
-                    int k = 0;
+                if (astring.length == 0) {
+                    astring = new String[map.size()][];
+                    i = 0;
 
-                    for(String string : map.keySet()) {
-                        strings[k++] = new String[]{string};
+                    String s;
+
+                    for (Iterator iterator = map.keySet().iterator(); iterator.hasNext(); astring[i++] = new String[]{s}) {
+                        s = (String) iterator.next();
                     }
                 }
 
-                for(String[] strings2 : strings) {
-                    if (strings2.length == 0 && map.isEmpty()) {
+                String[][] astring1 = astring;
+                int k = astring.length;
+
+                int l;
+
+                for (j = 0; j < k; ++j) {
+                    String[] astring2 = astring1[j];
+
+                    if (astring2.length == 0 && map.isEmpty()) {
                         throw new JsonSyntaxException("Requirement entry cannot be empty");
                     }
 
-                    for(String string2 : strings2) {
-                        if (!map.containsKey(string2)) {
-                            throw new JsonSyntaxException("Unknown required criterion '" + string2 + "'");
+                    String[] astring3 = astring2;
+
+                    l = astring2.length;
+
+                    for (int i1 = 0; i1 < l; ++i1) {
+                        String s1 = astring3[i1];
+
+                        if (!map.containsKey(s1)) {
+                            throw new JsonSyntaxException("Unknown required criterion '" + s1 + "'");
                         }
                     }
                 }
 
-                for(String string3 : map.keySet()) {
-                    boolean bl = false;
+                Iterator iterator1 = map.keySet().iterator();
 
-                    for(String[] strings3 : strings) {
-                        if (ArrayUtils.contains(strings3, string3)) {
-                            bl = true;
-                            break;
+                while (iterator1.hasNext()) {
+                    String s2 = (String) iterator1.next();
+                    boolean flag = false;
+                    String[][] astring4 = astring;
+                    int j1 = astring.length;
+
+                    l = 0;
+
+                    while (true) {
+                        if (l < j1) {
+                            String[] astring5 = astring4[l];
+
+                            if (!ArrayUtils.contains(astring5, s2)) {
+                                ++l;
+                                continue;
+                            }
+
+                            flag = true;
                         }
-                    }
 
-                    if (!bl) {
-                        throw new JsonSyntaxException("Criterion '" + string3 + "' isn't a requirement for completion. This isn't supported behaviour, all criteria must be required.");
+                        if (!flag) {
+                            throw new JsonSyntaxException("Criterion '" + s2 + "' isn't a requirement for completion. This isn't supported behaviour, all criteria must be required.");
+                        }
+                        break;
                     }
                 }
 
-                return new Advancement.Builder(resourceLocation, displayInfo, advancementRewards, map, strings);
+                return new Advancement.Builder(minecraftkey, advancementdisplay, advancementrewards, map, astring);
             }
         }
 
         public static Advancement.Builder fromNetwork(FriendlyByteBuf buf) {
-            ResourceLocation resourceLocation = buf.readNullable(FriendlyByteBuf::readResourceLocation);
-            DisplayInfo displayInfo = buf.readNullable(DisplayInfo::fromNetwork);
+            ResourceLocation minecraftkey = (ResourceLocation) buf.readNullable(FriendlyByteBuf::readResourceLocation);
+            DisplayInfo advancementdisplay = (DisplayInfo) buf.readNullable(DisplayInfo::fromNetwork);
             Map<String, Criterion> map = Criterion.criteriaFromNetwork(buf);
-            String[][] strings = new String[buf.readVarInt()][];
+            String[][] astring = new String[buf.readVarInt()][];
 
-            for(int i = 0; i < strings.length; ++i) {
-                strings[i] = new String[buf.readVarInt()];
+            for (int i = 0; i < astring.length; ++i) {
+                astring[i] = new String[buf.readVarInt()];
 
-                for(int j = 0; j < strings[i].length; ++j) {
-                    strings[i][j] = buf.readUtf();
+                for (int j = 0; j < astring[i].length; ++j) {
+                    astring[i][j] = buf.readUtf();
                 }
             }
 
-            return new Advancement.Builder(resourceLocation, displayInfo, AdvancementRewards.EMPTY, map, strings);
+            return new Advancement.Builder(minecraftkey, advancementdisplay, AdvancementRewards.EMPTY, map, astring);
         }
 
         public Map<String, Criterion> getCriteria() {
