Newer
Older
ChallengeSystem / Challenge / src / main / java / de / fanta / challenge / challenges / AllAdvancementsChallenge.java
@fanta fanta on 7 Jun 2024 6 KB ja
package de.fanta.challenge.challenges;

import com.destroystokyo.paper.event.player.PlayerAdvancementCriterionGrantEvent;
import de.fanta.challenge.Challenge;
import de.fanta.challenge.events.TimerChangedEvent;
import de.fanta.challenge.utils.ChatUtil;
import de.fanta.challenge.utils.Config;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.bossbar.BossBar;
import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit;
import org.bukkit.NamespacedKey;
import org.bukkit.advancement.Advancement;
import org.bukkit.advancement.AdvancementProgress;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerAdvancementDoneEvent;
import org.bukkit.event.player.PlayerJoinEvent;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;

public class AllAdvancementsChallenge implements Listener {

    public static BossBar bossBar;
    private static boolean running;
    private static final Challenge plugin = Challenge.getPlugin();

    @EventHandler
    public void onActivation(TimerChangedEvent event) {
        if (Config.getBoolean("alladvancements")) {
            if (event.isRunning()) {
                start();
            } else {
                stop();
            }
        }
    }


    @EventHandler
    public void onAdvancementDone(PlayerAdvancementDoneEvent e) {
        if (isRunning()) {
            createAdvancementString(e.getPlayer());
        }
    }

    @EventHandler
    public void onAdvancementCriteria(PlayerAdvancementCriterionGrantEvent e) {
        if (isRunning()) {
            createAdvancementString(e.getPlayer());
        }
    }

    @EventHandler
    public void onPlayerJoin(PlayerJoinEvent e) {
        if (!isRunning()) {
            return;
        }
        bossBar.addViewer(e.getPlayer());
        setAdvancementsToPlayer();
    }

    public static boolean isRunning() {
        return running;
    }

    public static void setRunning(boolean run) {
        running = run;
    }

    private static void updateBossbar() {
        int done = countDone();
        Component bossBarTitle = Component.text("(" + done + "/" + plugin.getAdvancements().size() + ") Advancements", ChatUtil.GREEN);
        float progress = done * 100.0f / plugin.getAdvancements().size() / 100.0f;
        if (bossBar == null) {
            bossBar = BossBar.bossBar(bossBarTitle, progress, BossBar.Color.GREEN, BossBar.Overlay.PROGRESS);
        } else {
            bossBar.name(bossBarTitle);
        }
        bossBar.progress(progress);
    }

    private void createAdvancementString(Player player) {
        ConfigurationSection advancements = Config.createSection("advancements");
        ArrayList<String> advancementsDone = new ArrayList<>();
        ConfigurationSection progress = advancements.createSection("progress");
        Iterator<Advancement> it = Bukkit.advancementIterator();
        while (it.hasNext()) {
            Advancement a = it.next();
            NamespacedKey key = a.getKey();
            if (key.getNamespace().equals(NamespacedKey.MINECRAFT) && !key.getKey().startsWith("recipes/")) {
                AdvancementProgress ap = player.getAdvancementProgress(a);
                if (ap.isDone()) {
                    advancementsDone.add(key.getKey());
                } else {
                    Collection<String> ac = ap.getAwardedCriteria();
                    if (!ac.isEmpty()) {
                        progress.set(key.getKey(), new ArrayList<>(ac));
                    }
                }
            }
        }
        advancements.set("done", advancementsDone);
        plugin.saveConfig();

        setAdvancementsToPlayer();
    }

    private static void setAdvancementsToPlayer() {
        if (Config.contains("advancements")) {
            ConfigurationSection advancements = Config.getConfigurationSection("advancements");
            if (advancements != null) {
                HashSet<String> done = new HashSet<>(advancements.getStringList("done"));
                ConfigurationSection progress = advancements.getConfigurationSection("progress");
                if (progress == null) {
                    return;
                }
                Iterator<Advancement> it = Bukkit.advancementIterator();
                while (it.hasNext()) {
                    Advancement a = it.next();
                    NamespacedKey key = a.getKey();
                    if (key.getNamespace().equals(NamespacedKey.MINECRAFT) && !key.getKey().startsWith("recipes/")) {
                        for (Player pp : plugin.getVanish().getPlayerListWithoutVanishPlayers()) {
                            AdvancementProgress ap = pp.getAdvancementProgress(a);
                            if (done.contains(key.getKey())) {
                                if (!ap.isDone()) {
                                    for (String crit : ap.getRemainingCriteria()) {
                                        ap.awardCriteria(crit);
                                    }
                                }
                            } else if (progress.contains(key.getKey())) {
                                List<String> parts = progress.getStringList(key.getKey());
                                for (String part : parts) {
                                    ap.awardCriteria(part);
                                }
                            }
                        }
                    }
                }
            }
        }
        updateBossbar();
    }

    private static int countDone() {
        int i = 0;
        ConfigurationSection advancements = Config.getConfigurationSection("advancements");
        if (advancements != null) {
            HashSet<String> done = new HashSet<>(advancements.getStringList("done"));
            for (String ignored : done) {
                i++;
            }
        }
        return i;
    }

    public static void start() {
        setAdvancementsToPlayer();
        updateBossbar();
        for (Player pp : Bukkit.getOnlinePlayers()) {
            bossBar.addViewer(pp);
        }
        setRunning(true);
    }

    public static void stop() {
        if (bossBar != null) {
            bossBar.viewers().forEach(bossBarViewer -> bossBar.removeViewer((Audience) bossBarViewer));
        }
        setRunning(false);
    }
}