/* * Decompiled with CFR 0.152. * * Could not load the following classes: * com.google.common.collect.Lists * com.google.common.collect.Maps * com.mojang.datafixers.kinds.App * com.mojang.datafixers.kinds.Applicative * com.mojang.serialization.Codec * com.mojang.serialization.codecs.RecordCodecBuilder * org.jspecify.annotations.Nullable */ package net.minecraft.advancements; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.mojang.datafixers.kinds.App; import com.mojang.datafixers.kinds.Applicative; import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; import java.time.Instant; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Comparator; import java.util.HashMap; import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; import net.minecraft.advancements.AdvancementRequirements; import net.minecraft.advancements.CriterionProgress; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.chat.Component; import net.minecraft.util.ExtraCodecs; import net.minecraft.util.Util; import org.jspecify.annotations.Nullable; public class AdvancementProgress implements Comparable { private static final DateTimeFormatter OBTAINED_TIME_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss Z", Locale.ROOT); private static final Codec OBTAINED_TIME_CODEC = ExtraCodecs.temporalCodec(OBTAINED_TIME_FORMAT).xmap(Instant::from, instant -> instant.atZone(ZoneId.systemDefault())); private static final Codec> CRITERIA_CODEC = Codec.unboundedMap((Codec)Codec.STRING, OBTAINED_TIME_CODEC).xmap(map -> Util.mapValues(map, CriterionProgress::new), map -> map.entrySet().stream().filter(e -> ((CriterionProgress)e.getValue()).isDone()).collect(Collectors.toMap(Map.Entry::getKey, e -> Objects.requireNonNull(((CriterionProgress)e.getValue()).getObtained())))); public static final Codec CODEC = RecordCodecBuilder.create(i -> i.group((App)CRITERIA_CODEC.optionalFieldOf("criteria", Map.of()).forGetter(a -> a.criteria), (App)Codec.BOOL.fieldOf("done").orElse((Object)true).forGetter(AdvancementProgress::isDone)).apply((Applicative)i, (criteria, done) -> new AdvancementProgress(new HashMap((Map)criteria)))); private final Map criteria; private AdvancementRequirements requirements = AdvancementRequirements.EMPTY; private AdvancementProgress(Map criteria) { this.criteria = criteria; } public AdvancementProgress() { this.criteria = Maps.newHashMap(); } public void update(AdvancementRequirements requirements) { Set names = requirements.names(); this.criteria.entrySet().removeIf(entry -> !names.contains(entry.getKey())); for (String name : names) { this.criteria.putIfAbsent(name, new CriterionProgress()); } this.requirements = requirements; } public boolean isDone() { return this.requirements.test(this::isCriterionDone); } public boolean hasProgress() { for (CriterionProgress progress : this.criteria.values()) { if (!progress.isDone()) continue; return true; } return false; } public boolean grantProgress(String name) { CriterionProgress progress = this.criteria.get(name); if (progress != null && !progress.isDone()) { progress.grant(); return true; } return false; } public boolean revokeProgress(String name) { CriterionProgress progress = this.criteria.get(name); if (progress != null && progress.isDone()) { progress.revoke(); return true; } return false; } public String toString() { return "AdvancementProgress{criteria=" + String.valueOf(this.criteria) + ", requirements=" + String.valueOf(this.requirements) + "}"; } public void serializeToNetwork(FriendlyByteBuf output) { output.writeMap(this.criteria, FriendlyByteBuf::writeUtf, (b, v) -> v.serializeToNetwork((FriendlyByteBuf)((Object)b))); } public static AdvancementProgress fromNetwork(FriendlyByteBuf input) { Map criteria = input.readMap(FriendlyByteBuf::readUtf, CriterionProgress::fromNetwork); return new AdvancementProgress(criteria); } public @Nullable CriterionProgress getCriterion(String id) { return this.criteria.get(id); } private boolean isCriterionDone(String criterion) { CriterionProgress progress = this.getCriterion(criterion); return progress != null && progress.isDone(); } public float getPercent() { if (this.criteria.isEmpty()) { return 0.0f; } float total = this.requirements.size(); float complete = this.countCompletedRequirements(); return complete / total; } public @Nullable Component getProgressText() { if (this.criteria.isEmpty()) { return null; } int total = this.requirements.size(); if (total <= 1) { return null; } int complete = this.countCompletedRequirements(); return Component.translatable("advancements.progress", complete, total); } private int countCompletedRequirements() { return this.requirements.count(this::isCriterionDone); } public Iterable getRemainingCriteria() { ArrayList remaining = Lists.newArrayList(); for (Map.Entry entry : this.criteria.entrySet()) { if (entry.getValue().isDone()) continue; remaining.add(entry.getKey()); } return remaining; } public Iterable getCompletedCriteria() { ArrayList completed = Lists.newArrayList(); for (Map.Entry entry : this.criteria.entrySet()) { if (!entry.getValue().isDone()) continue; completed.add(entry.getKey()); } return completed; } public @Nullable Instant getFirstProgressDate() { return this.criteria.values().stream().map(CriterionProgress::getObtained).filter(Objects::nonNull).min(Comparator.naturalOrder()).orElse(null); } @Override public int compareTo(AdvancementProgress o) { Instant ourSmallestDate = this.getFirstProgressDate(); Instant theirSmallestDate = o.getFirstProgressDate(); if (ourSmallestDate == null && theirSmallestDate != null) { return 1; } if (ourSmallestDate != null && theirSmallestDate == null) { return -1; } if (ourSmallestDate == null && theirSmallestDate == null) { return 0; } return ourSmallestDate.compareTo(theirSmallestDate); } }