File size: 5,127 Bytes
d46f4a3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package net.minecraft.client.multiplayer;

import com.mojang.logging.LogUtils;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Map.Entry;
import javax.annotation.Nullable;
import net.minecraft.advancements.AdvancementHolder;
import net.minecraft.advancements.AdvancementNode;
import net.minecraft.advancements.AdvancementProgress;
import net.minecraft.advancements.AdvancementTree;
import net.minecraft.advancements.DisplayInfo;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.components.toasts.AdvancementToast;
import net.minecraft.client.telemetry.WorldSessionTelemetryManager;
import net.minecraft.network.protocol.game.ClientboundUpdateAdvancementsPacket;
import net.minecraft.network.protocol.game.ServerboundSeenAdvancementsPacket;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.slf4j.Logger;

@OnlyIn(Dist.CLIENT)
public class ClientAdvancements {
    private static final Logger LOGGER = LogUtils.getLogger();
    private final Minecraft minecraft;
    private final WorldSessionTelemetryManager telemetryManager;
    private final AdvancementTree tree = new AdvancementTree();
    private final Map<AdvancementHolder, AdvancementProgress> progress = new Object2ObjectOpenHashMap<>();
    @Nullable
    private ClientAdvancements.Listener listener;
    @Nullable
    private AdvancementHolder selectedTab;

    public ClientAdvancements(Minecraft p_286782_, WorldSessionTelemetryManager p_286391_) {
        this.minecraft = p_286782_;
        this.telemetryManager = p_286391_;
    }

    public void update(ClientboundUpdateAdvancementsPacket p_104400_) {
        if (p_104400_.shouldReset()) {
            this.tree.clear();
            this.progress.clear();
        }

        this.tree.remove(p_104400_.getRemoved());
        this.tree.addAll(p_104400_.getAdded());

        for (Entry<ResourceLocation, AdvancementProgress> entry : p_104400_.getProgress().entrySet()) {
            AdvancementNode advancementnode = this.tree.get(entry.getKey());
            if (advancementnode != null) {
                AdvancementProgress advancementprogress = entry.getValue();
                advancementprogress.update(advancementnode.advancement().requirements());
                this.progress.put(advancementnode.holder(), advancementprogress);
                if (this.listener != null) {
                    this.listener.onUpdateAdvancementProgress(advancementnode, advancementprogress);
                }

                if (!p_104400_.shouldReset() && advancementprogress.isDone()) {
                    if (this.minecraft.level != null) {
                        this.telemetryManager.onAdvancementDone(this.minecraft.level, advancementnode.holder());
                    }

                    Optional<DisplayInfo> optional = advancementnode.advancement().display();
                    if (optional.isPresent() && optional.get().shouldShowToast()) {
                        this.minecraft.getToastManager().addToast(new AdvancementToast(advancementnode.holder()));
                    }
                }
            } else {
                LOGGER.warn("Server informed client about progress for unknown advancement {}", entry.getKey());
            }
        }
    }

    public AdvancementTree getTree() {
        return this.tree;
    }

    public void setSelectedTab(@Nullable AdvancementHolder p_298261_, boolean p_104403_) {
        ClientPacketListener clientpacketlistener = this.minecraft.getConnection();
        if (clientpacketlistener != null && p_298261_ != null && p_104403_) {
            clientpacketlistener.send(ServerboundSeenAdvancementsPacket.openedTab(p_298261_));
        }

        if (this.selectedTab != p_298261_) {
            this.selectedTab = p_298261_;
            if (this.listener != null) {
                this.listener.onSelectedTabChanged(p_298261_);
            }
        }
    }

    public void setListener(@Nullable ClientAdvancements.Listener p_104398_) {
        this.listener = p_104398_;
        this.tree.setListener(p_104398_);
        if (p_104398_ != null) {
            this.progress.forEach((p_297914_, p_300709_) -> {
                AdvancementNode advancementnode = this.tree.get(p_297914_);
                if (advancementnode != null) {
                    p_104398_.onUpdateAdvancementProgress(advancementnode, p_300709_);
                }
            });
            p_104398_.onSelectedTabChanged(this.selectedTab);
        }
    }

    @Nullable
    public AdvancementHolder get(ResourceLocation p_301273_) {
        AdvancementNode advancementnode = this.tree.get(p_301273_);
        return advancementnode != null ? advancementnode.holder() : null;
    }

    @OnlyIn(Dist.CLIENT)
    public interface Listener extends AdvancementTree.Listener {
        void onUpdateAdvancementProgress(AdvancementNode p_299734_, AdvancementProgress p_104405_);

        void onSelectedTabChanged(@Nullable AdvancementHolder p_301401_);
    }
}