package net.minecraft.advancements; import com.mojang.logging.LogUtils; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import net.minecraft.resources.ResourceLocation; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; public class AdvancementTree { private static final Logger LOGGER = LogUtils.getLogger(); private final Map nodes = new Object2ObjectOpenHashMap<>(); private final Set roots = new ObjectLinkedOpenHashSet<>(); private final Set tasks = new ObjectLinkedOpenHashSet<>(); @Nullable private AdvancementTree.Listener listener; private void remove(AdvancementNode node) { for (AdvancementNode advancementNode : node.children()) { this.remove(advancementNode); } LOGGER.info("Forgot about advancement {}", node.holder()); this.nodes.remove(node.holder().id()); if (node.parent() == null) { this.roots.remove(node); if (this.listener != null) { this.listener.onRemoveAdvancementRoot(node); } } else { this.tasks.remove(node); if (this.listener != null) { this.listener.onRemoveAdvancementTask(node); } } } public void remove(Set advancements) { for (ResourceLocation resourceLocation : advancements) { AdvancementNode advancementNode = (AdvancementNode)this.nodes.get(resourceLocation); if (advancementNode == null) { LOGGER.warn("Told to remove advancement {} but I don't know what that is", resourceLocation); } else { this.remove(advancementNode); } } } public void addAll(Collection advancements) { List list = new ArrayList(advancements); while (!list.isEmpty()) { if (!list.removeIf(this::tryInsert)) { LOGGER.error("Couldn't load advancements: {}", list); break; } } LOGGER.info("Loaded {} advancements", this.nodes.size()); } private boolean tryInsert(AdvancementHolder advancement) { Optional optional = advancement.value().parent(); AdvancementNode advancementNode = (AdvancementNode)optional.map(this.nodes::get).orElse(null); if (advancementNode == null && optional.isPresent()) { return false; } else { AdvancementNode advancementNode2 = new AdvancementNode(advancement, advancementNode); if (advancementNode != null) { advancementNode.addChild(advancementNode2); } this.nodes.put(advancement.id(), advancementNode2); if (advancementNode == null) { this.roots.add(advancementNode2); if (this.listener != null) { this.listener.onAddAdvancementRoot(advancementNode2); } } else { this.tasks.add(advancementNode2); if (this.listener != null) { this.listener.onAddAdvancementTask(advancementNode2); } } return true; } } public void clear() { this.nodes.clear(); this.roots.clear(); this.tasks.clear(); if (this.listener != null) { this.listener.onAdvancementsCleared(); } } public Iterable roots() { return this.roots; } public Collection nodes() { return this.nodes.values(); } @Nullable public AdvancementNode get(ResourceLocation id) { return (AdvancementNode)this.nodes.get(id); } @Nullable public AdvancementNode get(AdvancementHolder advancement) { return (AdvancementNode)this.nodes.get(advancement.id()); } public void setListener(@Nullable AdvancementTree.Listener listener) { this.listener = listener; if (listener != null) { for (AdvancementNode advancementNode : this.roots) { listener.onAddAdvancementRoot(advancementNode); } for (AdvancementNode advancementNode : this.tasks) { listener.onAddAdvancementTask(advancementNode); } } } public interface Listener { void onAddAdvancementRoot(AdvancementNode advancement); void onRemoveAdvancementRoot(AdvancementNode advancement); void onAddAdvancementTask(AdvancementNode advancement); void onRemoveAdvancementTask(AdvancementNode advancement); void onAdvancementsCleared(); } }