diff --git a/src/main/java/com/alttd/altitudequests/AQuest.java b/src/main/java/com/alttd/altitudequests/AQuest.java index 4ec48e4..86d5623 100644 --- a/src/main/java/com/alttd/altitudequests/AQuest.java +++ b/src/main/java/com/alttd/altitudequests/AQuest.java @@ -4,6 +4,7 @@ import com.alttd.altitudequests.commands.CommandManager; import com.alttd.altitudequests.config.*; import com.alttd.altitudequests.events.*; import com.alttd.altitudequests.objects.Quest; +import com.alttd.altitudequests.util.AutoHideBossBar; import com.alttd.altitudequests.util.Logger; import com.alttd.altitudequests.util.Utilities; import com.alttd.datalock.DataLockAPI; @@ -37,6 +38,7 @@ public final class AQuest extends JavaPlugin { } else { dataLockAPI.registerChannel("aquest:player-data"); } + AutoHideBossBar.initiate(); Logger.info("--------------------------------------------------"); Logger.info("AQuest started"); @@ -69,6 +71,11 @@ public final class AQuest extends JavaPlugin { getServer().getPluginManager().registerEvents(new EntityBreed(), this); getServer().getPluginManager().registerEvents(new DonNotMessWithNPC(), this); getServer().getPluginManager().registerEvents(new DataLock(), this); + getServer().getPluginManager().registerEvents(new ItemCaught(), this); +// getServer().getPluginManager().registerEvents(new PotionBrewingStarted(), this); +// getServer().getPluginManager().registerEvents(new PotionBrewingFinished(), this); + getServer().getPluginManager().registerEvents(new FinishedRaid(), this); + // getServer().getMessenger().registerOutgoingPluginChannel(this, "aquest:player-data"); // getServer().getMessenger().registerIncomingPluginChannel(this, "aquest:player-data", new PluginMessageListener()); } diff --git a/src/main/java/com/alttd/altitudequests/commands/CommandManager.java b/src/main/java/com/alttd/altitudequests/commands/CommandManager.java index 23e1125..4cc7c7c 100644 --- a/src/main/java/com/alttd/altitudequests/commands/CommandManager.java +++ b/src/main/java/com/alttd/altitudequests/commands/CommandManager.java @@ -35,7 +35,8 @@ public class CommandManager implements CommandExecutor, TabExecutor { new CommandChangeQuest(), new CommandTurnIn(), new CommandSetQuest(), - new CommandGetReward()); + new CommandGetReward(), + new CommandProgress()); } @Override diff --git a/src/main/java/com/alttd/altitudequests/commands/subcommands/CommandProgress.java b/src/main/java/com/alttd/altitudequests/commands/subcommands/CommandProgress.java index 4039b33..4f78cf3 100644 --- a/src/main/java/com/alttd/altitudequests/commands/subcommands/CommandProgress.java +++ b/src/main/java/com/alttd/altitudequests/commands/subcommands/CommandProgress.java @@ -1,15 +1,55 @@ package com.alttd.altitudequests.commands.subcommands; +import com.alttd.altitudequests.AQuest; import com.alttd.altitudequests.commands.SubCommand; +import com.alttd.altitudequests.config.MessagesConfig; +import com.alttd.altitudequests.objects.Quest; +import com.alttd.altitudequests.util.ProgressBookOpener; import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; +import java.util.HashSet; import java.util.List; +import java.util.Set; +import java.util.UUID; public class CommandProgress extends SubCommand { //TODO show player current quest progress + + private static final Set inProcess = new HashSet<>(); @Override public boolean onCommand(CommandSender commandSender, String[] args) { - return false; + if (!(commandSender instanceof Player player)) { + commandSender.sendMiniMessage(MessagesConfig.NO_CONSOLE, null); + return true; + } + if (player == null || !player.hasPlayedBefore()) { + commandSender.sendMiniMessage(getHelpMessage(), null); + return true; + } + Quest dailyQuest = Quest.getDailyQuest(player.getUniqueId()); + if (dailyQuest == null) { + player.sendMiniMessage("You have no active quests.", null); + return true; + } + if (dailyQuest.isDone()) { + player.sendMiniMessage("You already completed the daily quest.", null); + return true; + } + final UUID uniqueId = player.getUniqueId(); + if (inProcess.contains(uniqueId)) { + return true; + } + inProcess.add(uniqueId); + new BukkitRunnable() { + @Override + public void run() { + ProgressBookOpener.openProgressBook(player); + inProcess.remove(uniqueId); + } + }.runTaskAsynchronously(AQuest.getInstance()); + return true; } @Override diff --git a/src/main/java/com/alttd/altitudequests/commands/subcommands/CommandSetQuest.java b/src/main/java/com/alttd/altitudequests/commands/subcommands/CommandSetQuest.java index 195dd45..3927395 100644 --- a/src/main/java/com/alttd/altitudequests/commands/subcommands/CommandSetQuest.java +++ b/src/main/java/com/alttd/altitudequests/commands/subcommands/CommandSetQuest.java @@ -4,10 +4,7 @@ import com.alttd.altitudequests.AQuest; import com.alttd.altitudequests.commands.SubCommand; import com.alttd.altitudequests.config.MessagesConfig; import com.alttd.altitudequests.objects.Quest; -import com.alttd.altitudequests.objects.quests.BreedMobsQuest; -import com.alttd.altitudequests.objects.quests.CollectDropsQuest; -import com.alttd.altitudequests.objects.quests.KillMobsQuest; -import com.alttd.altitudequests.objects.quests.MineQuest; +import com.alttd.altitudequests.objects.quests.*; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; import org.bukkit.Bukkit; @@ -17,8 +14,6 @@ import org.bukkit.scheduler.BukkitRunnable; import java.util.ArrayList; import java.util.List; -import java.util.Locale; -import java.util.Optional; import java.util.stream.Collectors; public class CommandSetQuest extends SubCommand { @@ -68,6 +63,7 @@ public class CommandSetQuest extends SubCommand { case "collectdropsquest" -> res.addAll(CollectDropsQuest.getSubTypes()); case "killmobsquest" -> res.addAll(KillMobsQuest.getSubTypes()); case "minequest" -> res.addAll(MineQuest.getSubTypes()); + case "otherquest" -> res.addAll(OtherQuest.getSubTypes()); default -> res.add("invalid quest type"); } } diff --git a/src/main/java/com/alttd/altitudequests/config/Config.java b/src/main/java/com/alttd/altitudequests/config/Config.java index 7dbf058..b34fec1 100644 --- a/src/main/java/com/alttd/altitudequests/config/Config.java +++ b/src/main/java/com/alttd/altitudequests/config/Config.java @@ -1,10 +1,10 @@ package com.alttd.altitudequests.config; import java.io.File; +import java.time.Duration; import java.util.List; public final class Config extends AbstractConfig { - static Config config; static int version; public Config() { @@ -21,6 +21,8 @@ public final class Config extends AbstractConfig { public static String QUEST_BOOK_AUTHOR = "Scruff"; public static String QUEST_BOOK_TITLE = "Quest Title"; + public static String PROGRESS_BOOK_AUTHOR = "Scruff"; + public static String PROGRESS_BOOK_TITLE = "Quest Title"; public static List QUEST_PAGES = List.of(""" Hey @@ -31,6 +33,16 @@ public final class Config extends AbstractConfig { * : / + """); + public static List PROGRESS_PAGES = List.of(""" + Hey + + Your quest progress: + * Quest: + * Type: + * : / + * : / + """); private static void loadBook() { QUEST_BOOK_AUTHOR = config.getString("book.author", QUEST_BOOK_AUTHOR); @@ -38,21 +50,31 @@ public final class Config extends AbstractConfig { QUEST_PAGES = config.getStringList("book.pages", QUEST_PAGES); } + private static void loadProgressBook() { + PROGRESS_BOOK_AUTHOR = config.getString("progressBook.author", PROGRESS_BOOK_AUTHOR); + PROGRESS_BOOK_TITLE = config.getString("progressBook.title", PROGRESS_BOOK_TITLE); + PROGRESS_PAGES = config.getStringList("progressBook.pages", PROGRESS_PAGES); + } + public static String NPC_NAME = "Scruff"; public static boolean DEBUG = false; + public static Duration BOSS_BAR_AUTO_HIDE; private static void loadSettings() { NPC_NAME = config.getString("settings.npc-name", NPC_NAME); DEBUG = config.getBoolean("settings.debug", DEBUG); + BOSS_BAR_AUTO_HIDE = Duration.ofSeconds(config.getInt("settings.boss-bar-auto-hide-seconds", 10)); } public static int MINE_QUEST_FREQ = 1; public static int KILL_QUEST_FREQ = 1; public static int COLLECT_QUEST_FREQ = 1; public static int BREED_QUEST_FREQ = 1; + public static int OTHER_QUEST_FRQ = 1; private static void loadQuestTypeFrequency() { MINE_QUEST_FREQ = config.getInt("quest-type-frequency.mine", MINE_QUEST_FREQ); KILL_QUEST_FREQ = config.getInt("quest-type-frequency.kill", KILL_QUEST_FREQ); COLLECT_QUEST_FREQ = config.getInt("quest-type-frequency.collect", COLLECT_QUEST_FREQ); BREED_QUEST_FREQ = config.getInt("quest-type-frequency.breed", BREED_QUEST_FREQ); + OTHER_QUEST_FRQ = config.getInt("quest-type-frequency.other", OTHER_QUEST_FRQ); } } diff --git a/src/main/java/com/alttd/altitudequests/config/QuestsConfig.java b/src/main/java/com/alttd/altitudequests/config/QuestsConfig.java index b93be60..38eae08 100644 --- a/src/main/java/com/alttd/altitudequests/config/QuestsConfig.java +++ b/src/main/java/com/alttd/altitudequests/config/QuestsConfig.java @@ -4,6 +4,7 @@ import com.alttd.altitudequests.objects.variants.BreedMobsQuestObject; import com.alttd.altitudequests.objects.variants.CollectDropsQuestObject; import com.alttd.altitudequests.objects.variants.KillMobsQuestObject; import com.alttd.altitudequests.objects.variants.MineQuestObject; +import com.alttd.altitudequests.objects.variants.OtherQuestObject; import com.alttd.altitudequests.util.Logger; import org.bukkit.Material; import org.bukkit.configuration.ConfigurationSection; @@ -33,6 +34,8 @@ public class QuestsConfig extends AbstractConfig { public static String MINE_STEP_2 = "Turned in"; public static String MINE_TURN_IN = "Click here to turn in your "; public static List MINE_COMMANDS = List.of("broadcast Finished their daily quest!"); + public static Material material; + public static Material turnInMaterial; private static void loadMineQuests() { MINE_QUESTS.clear(); @@ -44,10 +47,18 @@ public class QuestsConfig extends AbstractConfig { Set keys = configurationSection.getKeys(false); for (String key : keys) { try { - Material material = Material.valueOf(configurationSection.getString(key + ".material")); + material = Material.valueOf(configurationSection.getString(key + ".material")); + if (configurationSection.getString(key + ".turnInMaterial") == null) { + turnInMaterial = material; + } + else { + turnInMaterial = Material.valueOf(configurationSection.getString(key + ".turnInMaterial")); + } + MINE_QUESTS.add(new MineQuestObject(key, configurationSection.getString(key + ".name"), material, + turnInMaterial, configurationSection.getStringList(key + ".quest-pages"), configurationSection.getStringList(key + ".done-pages"), configurationSection.getInt(key + ".amount-min"), @@ -144,6 +155,54 @@ public class QuestsConfig extends AbstractConfig { COLLECT_DROPS_COMMANDS = config.getStringList("collect_drops.commands", COLLECT_DROPS_COMMANDS); } + public static List OTHER_QUEST = new ArrayList<>(); + public static String OTHER_QUEST_NAME = "Other quest"; + public static String OTHER_TURN_IN = "Click here to turn in your "; + public static List OTHER_COMMANDS = List.of("broadcast Finished their daily quest!"); + public static Material item; + public static EntityType entityType; + + private static void loadOtherQuests() { + OTHER_QUEST.clear(); + ConfigurationSection configurationSection = config.getConfigurationSection("other.possible_tasks"); + if (configurationSection == null) { + Logger.warning("No other quests in config"); + return; + } + Set keys = configurationSection.getKeys(false); + for (String key : keys) { + try { + item = Material.valueOf(configurationSection.getString(key + ".item")); + + if (configurationSection.getString(key + ".mob") == null) { + entityType = null; + } + else { + entityType = EntityType.valueOf(configurationSection.getString(key + ".mob")); + } + OTHER_QUEST.add(new OtherQuestObject(key, + configurationSection.getString(key + ".name"), + configurationSection.getString(key + ".category"), + item, + entityType, + configurationSection.getStringList(key + ".quest-pages"), + configurationSection.getStringList(key + ".done-pages"), + configurationSection.getInt(key + ".amount-min"), + configurationSection.getInt(key + ".amount-max"), + configurationSection.getString(key + ".step-1"), + configurationSection.getString(key + ".step-2"))); + if (Config.DEBUG) + Logger.info("Loaded Collect drops quest " + key); + } + catch (Exception e) { + e.printStackTrace(); + } + } + OTHER_QUEST_NAME = config.getString("other.name", OTHER_QUEST_NAME); + OTHER_TURN_IN = config.getString("other.turn-in", OTHER_TURN_IN); + OTHER_COMMANDS = config.getStringList("other.commands", OTHER_COMMANDS); + } + public static List BREED_MOB_QUEST = new ArrayList<>(); public static String BREED_MOB_QUEST_NAME = "Breed mobs quest"; public static String BREED_STEP_1 = "Bred"; diff --git a/src/main/java/com/alttd/altitudequests/events/EntityBucketed.java b/src/main/java/com/alttd/altitudequests/events/EntityBucketed.java index 23d396b..d4520d5 100644 --- a/src/main/java/com/alttd/altitudequests/events/EntityBucketed.java +++ b/src/main/java/com/alttd/altitudequests/events/EntityBucketed.java @@ -2,27 +2,28 @@ package com.alttd.altitudequests.events; import com.alttd.altitudequests.objects.Quest; import com.alttd.altitudequests.objects.quests.CollectDropsQuest; +import com.alttd.altitudequests.objects.quests.OtherQuest; +import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerBucketFillEvent; +import org.bukkit.event.player.PlayerBucketEntityEvent; import org.bukkit.inventory.ItemStack; -import java.util.List; - public class EntityBucketed implements Listener { @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onBucketFill(PlayerBucketFillEvent event) { + public void onBucketFill(PlayerBucketEntityEvent event) { Player player = event.getPlayer(); Quest dailyQuest = Quest.getDailyQuest(player.getUniqueId()); if (dailyQuest == null || dailyQuest.isDone()) return; - if (dailyQuest instanceof CollectDropsQuest collectDropsQuest) { - ItemStack itemStack = event.getItemStack(); - if (itemStack != null) - collectDropsQuest.collectDrops(List.of(itemStack)); + if (dailyQuest instanceof OtherQuest otherQuest) { + ItemStack itemStack = event.getEntityBucket(); + Entity entity = event.getEntity(); + if (itemStack != null && entity != null) + otherQuest.bucket(itemStack, entity); } } diff --git a/src/main/java/com/alttd/altitudequests/events/EntitySheared.java b/src/main/java/com/alttd/altitudequests/events/EntitySheared.java index cd486dc..567f714 100644 --- a/src/main/java/com/alttd/altitudequests/events/EntitySheared.java +++ b/src/main/java/com/alttd/altitudequests/events/EntitySheared.java @@ -1,15 +1,13 @@ package com.alttd.altitudequests.events; import com.alttd.altitudequests.objects.Quest; -import com.alttd.altitudequests.objects.quests.CollectDropsQuest; +import com.alttd.altitudequests.objects.quests.OtherQuest; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerShearEntityEvent; -import java.util.List; - public class EntitySheared implements Listener { @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) @@ -18,8 +16,8 @@ public class EntitySheared implements Listener { Quest dailyQuest = Quest.getDailyQuest(player.getUniqueId()); if (dailyQuest == null || dailyQuest.isDone()) return; - if (dailyQuest instanceof CollectDropsQuest collectDropsQuest) { - collectDropsQuest.collectDrops(List.of(event.getItem())); + if (dailyQuest instanceof OtherQuest otherQuest) { + otherQuest.shear(event.getEntity()); } } } diff --git a/src/main/java/com/alttd/altitudequests/events/FinishedRaid.java b/src/main/java/com/alttd/altitudequests/events/FinishedRaid.java new file mode 100644 index 0000000..cbbaee4 --- /dev/null +++ b/src/main/java/com/alttd/altitudequests/events/FinishedRaid.java @@ -0,0 +1,30 @@ +package com.alttd.altitudequests.events; + +import com.alttd.altitudequests.objects.Quest; +import com.alttd.altitudequests.objects.quests.OtherQuest; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.raid.RaidFinishEvent; + +import java.util.List; +import java.util.UUID; + +public class FinishedRaid implements Listener { + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onRaidFinish(RaidFinishEvent event) { + List winners = event.getWinners(); + for (Player player : winners) { + UUID uuid = player.getUniqueId(); + Quest dailyQuest = Quest.getDailyQuest(uuid); + if (dailyQuest == null || dailyQuest.isDone()) { + return; + } + if (dailyQuest instanceof OtherQuest otherQuest) { + otherQuest.raid(); + } + } + } +} diff --git a/src/main/java/com/alttd/altitudequests/events/ItemCaught.java b/src/main/java/com/alttd/altitudequests/events/ItemCaught.java new file mode 100644 index 0000000..2b2cea8 --- /dev/null +++ b/src/main/java/com/alttd/altitudequests/events/ItemCaught.java @@ -0,0 +1,32 @@ +package com.alttd.altitudequests.events; + +import com.alttd.altitudequests.objects.Quest; +import com.alttd.altitudequests.objects.quests.OtherQuest; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerFishEvent; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Item; +import org.bukkit.inventory.ItemStack; + +public class ItemCaught implements Listener { + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onItemCaught(PlayerFishEvent event) { + if (event.getCaught() == null || event.getCaught().getType() != EntityType.DROPPED_ITEM) { + return; //Only if an item was caught do further processing. Otherwise error might come up later + } + Player player = event.getPlayer(); + Quest dailyQuest = Quest.getDailyQuest(player.getUniqueId()); + if (dailyQuest == null || dailyQuest.isDone()) { + return; + } + if (dailyQuest instanceof OtherQuest otherQuest) { + Item item = (Item) event.getCaught(); + ItemStack caughtItem = item.getItemStack(); + otherQuest.fish(caughtItem); + } + } +} diff --git a/src/main/java/com/alttd/altitudequests/events/MineBlocks.java b/src/main/java/com/alttd/altitudequests/events/MineBlocks.java index 7fce06d..01d1262 100644 --- a/src/main/java/com/alttd/altitudequests/events/MineBlocks.java +++ b/src/main/java/com/alttd/altitudequests/events/MineBlocks.java @@ -22,5 +22,4 @@ public class MineBlocks implements Listener { if (quest instanceof MineQuest mineQuest) mineQuest.mine(event.getBlock()); } - } diff --git a/src/main/java/com/alttd/altitudequests/objects/Quest.java b/src/main/java/com/alttd/altitudequests/objects/Quest.java index fc89eef..dfff39a 100644 --- a/src/main/java/com/alttd/altitudequests/objects/Quest.java +++ b/src/main/java/com/alttd/altitudequests/objects/Quest.java @@ -4,12 +4,11 @@ import com.alttd.altitudequests.AQuest; import com.alttd.altitudequests.config.Config; import com.alttd.altitudequests.config.MessagesConfig; import com.alttd.altitudequests.database.Database; -import com.alttd.altitudequests.objects.quests.BreedMobsQuest; -import com.alttd.altitudequests.objects.quests.CollectDropsQuest; -import com.alttd.altitudequests.objects.quests.KillMobsQuest; -import com.alttd.altitudequests.objects.quests.MineQuest; +import com.alttd.altitudequests.objects.quests.*; import com.alttd.altitudequests.util.Logger; import com.alttd.altitudequests.util.Utilities; +import com.alttd.altitudequests.util.AutoHideBossBar; +import org.bukkit.boss.BarColor; import com.alttd.datalock.DataLockAPI; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.minimessage.MiniMessage; @@ -17,7 +16,6 @@ import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitRunnable; - import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.sql.PreparedStatement; @@ -29,7 +27,7 @@ import java.util.stream.Collectors; public abstract class Quest { private static final HashMap dailyQuests = new HashMap<>(); -// private static Quest weeklyQuest = null; + // private static Quest weeklyQuest = null; private static final List> possibleQuests = new ArrayList<>(); static { // maybe make this make more sense idk @@ -41,6 +39,8 @@ public abstract class Quest { possibleQuests.add(CollectDropsQuest.class); for (int i = 0; i < Config.BREED_QUEST_FREQ; i++) possibleQuests.add(BreedMobsQuest.class); + for (int i = 0; i < Config.OTHER_QUEST_FRQ; i++) + possibleQuests.add(OtherQuest.class); } private final UUID uuid; @@ -50,6 +50,8 @@ public abstract class Quest { private boolean isDone; private boolean rewardReceived; private final int amount; + private final AutoHideBossBar barProgressOne; + private final AutoHideBossBar barProgressTwo; public static synchronized void putDailyQuest(UUID uuid, Quest quest) { dailyQuests.put(uuid, quest); @@ -75,8 +77,8 @@ public abstract class Quest { dailyQuests.clear(); } - public Quest(UUID uuid, int step1, int step2, Variant variant, int amount, boolean rewardReceived) { - this.uuid = uuid; + public Quest(Player player, int step1, int step2, Variant variant, int amount, boolean rewardReceived) throws Exception { + this.uuid = player.getUniqueId(); this.step1 = step1; this.step2 = step2; this.variant = variant; @@ -84,11 +86,14 @@ public abstract class Quest { this.rewardReceived = rewardReceived; if (variant == null) { Logger.warning("Created % quest without a variant for %", this.getClass().getName(), uuid.toString()); + throw new Exception("Invalid variant"); } - if (variant != null && amount == -1) + if (amount == -1) this.amount = variant.calculateAmount(loadQuestsDoneThisMonth(uuid)); else this.amount = amount; + this.barProgressOne = new AutoHideBossBar(player, variant, "1", "Step One Progress", BarColor.GREEN); + this.barProgressTwo = new AutoHideBossBar(player, variant, "2", "Step Two Progress", BarColor.PURPLE); } private int loadQuestsDoneThisMonth(UUID uuid) { @@ -117,12 +122,17 @@ public abstract class Quest { Class questClass = possibleQuests.get(Utilities.randomOr0(possibleQuests.size() - 1)); try { - Constructor constructor = questClass.getDeclaredConstructor(UUID.class); - putDailyQuest(player.getUniqueId(), constructor.newInstance(player.getUniqueId())); - } catch (InvocationTargetException | IllegalAccessException | InstantiationException | NoSuchMethodException e) { + Constructor constructor = questClass.getDeclaredConstructor(Player.class); + putDailyQuest(player.getUniqueId(), constructor.newInstance(player)); + } catch (InvocationTargetException | IllegalAccessException | InstantiationException | + NoSuchMethodException e) { player.sendMiniMessage("Unable to create quest, contact an admin", null); e.printStackTrace(); - Logger.severe("% does not have a constructor with a UUID input or has improper access.", questClass.getName()); + Logger.severe("% does not have a constructor with a Player input or has improper access.", questClass.getName()); + } catch (Exception e) { + player.sendMiniMessage("Unable to create quest, contact an admin", null); + e.printStackTrace(); + Logger.severe("% could not be created due to invalid namespace key or variant.", questClass.getName()); } } @@ -130,7 +140,7 @@ public abstract class Quest { // Quest.weeklyQuest = newQuest; // } -// private static final HashSet queriedUsers = new HashSet<>(); + // private static final HashSet queriedUsers = new HashSet<>(); public static void tryLoadDailyQuest(UUID uuid) { // if (queriedUsers.contains(uuid)) // return; @@ -172,6 +182,7 @@ public abstract class Quest { Class aClass = any.get(); Constructor constructor; try { + Player player = Bukkit.getPlayer(uuid); if (Config.DEBUG) { Logger.info("quest: %, uuid: %, step1: %, step2: %, variant: %, amount: %, turnedIn:%", quest, @@ -182,10 +193,11 @@ public abstract class Quest { String.valueOf(amount), String.valueOf(turnedIn)); } - constructor = aClass.getConstructor(UUID.class, int.class, int.class, String.class, int.class, boolean.class); - Quest quest1 = constructor.newInstance(uuid, step_1_progress, step_2_progress, quest_variant, amount, turnedIn); + constructor = aClass.getConstructor(Player.class, int.class, int.class, String.class, int.class, boolean.class); + Quest quest1 = constructor.newInstance(player, step_1_progress, step_2_progress, quest_variant, amount, turnedIn); putDailyQuest(uuid, quest1); - } catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) { + } catch (NoSuchMethodException | IllegalAccessException | InstantiationException | + InvocationTargetException e) { e.printStackTrace(); return false; } @@ -290,6 +302,7 @@ public abstract class Quest { public void addStep1(int step1) { this.step1 += step1; + barProgressOne.show(((double) getStep1()) / getAmount()); } public int getStep2() { @@ -298,6 +311,7 @@ public abstract class Quest { public void addStep2(int step2) { this.step2 += step2; + barProgressTwo.show(((double) getStep2()) / getAmount()); } public void setDone(boolean done) { diff --git a/src/main/java/com/alttd/altitudequests/objects/quests/BreedMobsQuest.java b/src/main/java/com/alttd/altitudequests/objects/quests/BreedMobsQuest.java index d76e312..50644e9 100644 --- a/src/main/java/com/alttd/altitudequests/objects/quests/BreedMobsQuest.java +++ b/src/main/java/com/alttd/altitudequests/objects/quests/BreedMobsQuest.java @@ -18,15 +18,14 @@ import org.bukkit.entity.Player; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.List; -import java.util.UUID; import java.util.stream.Collectors; public class BreedMobsQuest extends Quest { private final BreedMobsQuestObject breedMobsQuestObject; - public BreedMobsQuest(UUID uuid) { - super(uuid, 0, 0, + public BreedMobsQuest(Player player) throws Exception { + super(player, 0, 0, QuestsConfig.BREED_MOB_QUEST.get(Utilities.randomOr0(QuestsConfig.BREED_MOB_QUEST.size() - 1)), -1, false); if (getVariant() instanceof BreedMobsQuestObject breedMobsQuestObject) this.breedMobsQuestObject = breedMobsQuestObject; @@ -38,8 +37,8 @@ public class BreedMobsQuest extends Quest { } } - public BreedMobsQuest(UUID uuid, int step1, int step2, String variant, int amount, boolean rewardReceived) { - super(uuid, step1, step2, QuestsConfig.BREED_MOB_QUEST.stream() + public BreedMobsQuest(Player player, int step1, int step2, String variant, int amount, boolean rewardReceived) throws Exception { + super(player, step1, step2, QuestsConfig.BREED_MOB_QUEST.stream() .filter(object -> variant.equals(object.getInternalName())) .findAny().orElse(null), amount, rewardReceived); if (getVariant() instanceof BreedMobsQuestObject breedMobsQuestObject) diff --git a/src/main/java/com/alttd/altitudequests/objects/quests/CollectDropsQuest.java b/src/main/java/com/alttd/altitudequests/objects/quests/CollectDropsQuest.java index ed4334f..3446a82 100644 --- a/src/main/java/com/alttd/altitudequests/objects/quests/CollectDropsQuest.java +++ b/src/main/java/com/alttd/altitudequests/objects/quests/CollectDropsQuest.java @@ -28,8 +28,8 @@ public class CollectDropsQuest extends Quest { private final CollectDropsQuestObject collectDropsQuestObject; - public CollectDropsQuest(UUID uuid) { - super(uuid, 0, 0, + public CollectDropsQuest(Player player) throws Exception { + super(player, 0, 0, QuestsConfig.COLLECT_DROPS_QUEST.get(Utilities.randomOr0(QuestsConfig.COLLECT_DROPS_QUEST.size() - 1)), -1, false); if (getVariant() instanceof CollectDropsQuestObject collectDropsQuestObject) this.collectDropsQuestObject = collectDropsQuestObject; @@ -41,8 +41,8 @@ public class CollectDropsQuest extends Quest { } } - public CollectDropsQuest(UUID uuid, int step1, int step2, String variant, int amount, boolean rewardReceived) { - super(uuid, step1, step2, QuestsConfig.COLLECT_DROPS_QUEST.stream() + public CollectDropsQuest(Player player, int step1, int step2, String variant, int amount, boolean rewardReceived) throws Exception { + super(player, step1, step2, QuestsConfig.COLLECT_DROPS_QUEST.stream() .filter(object -> variant.equals(object.getInternalName())) .findAny().orElse(null), amount, rewardReceived); if (getVariant() instanceof CollectDropsQuestObject collectDropsQuestObject) diff --git a/src/main/java/com/alttd/altitudequests/objects/quests/KillMobsQuest.java b/src/main/java/com/alttd/altitudequests/objects/quests/KillMobsQuest.java index 2cc07c3..87ffc74 100644 --- a/src/main/java/com/alttd/altitudequests/objects/quests/KillMobsQuest.java +++ b/src/main/java/com/alttd/altitudequests/objects/quests/KillMobsQuest.java @@ -25,8 +25,8 @@ public class KillMobsQuest extends Quest { private final KillMobsQuestObject killMobsQuestObject; - public KillMobsQuest(UUID uuid) { - super(uuid, 0, 0, + public KillMobsQuest(Player player) throws Exception { + super(player, 0, 0, QuestsConfig.KILL_MOB_QUEST.get(Utilities.randomOr0(QuestsConfig.KILL_MOB_QUEST.size() - 1)), -1, false); if (getVariant() instanceof KillMobsQuestObject killMobsQuestObject) this.killMobsQuestObject = killMobsQuestObject; @@ -38,8 +38,8 @@ public class KillMobsQuest extends Quest { } } - public KillMobsQuest(UUID uuid, int step1, int step2, String variant, int amount, boolean rewardReceived) { - super(uuid, step1, step2, QuestsConfig.KILL_MOB_QUEST.stream() + public KillMobsQuest(Player player, int step1, int step2, String variant, int amount, boolean rewardReceived) throws Exception { + super(player, step1, step2, QuestsConfig.KILL_MOB_QUEST.stream() .filter(object -> variant.equals(object.getInternalName())) .findAny().orElse(null), amount, rewardReceived); if (getVariant() instanceof KillMobsQuestObject killMobsQuestObject) diff --git a/src/main/java/com/alttd/altitudequests/objects/quests/MineQuest.java b/src/main/java/com/alttd/altitudequests/objects/quests/MineQuest.java index 5674b2d..431e865 100644 --- a/src/main/java/com/alttd/altitudequests/objects/quests/MineQuest.java +++ b/src/main/java/com/alttd/altitudequests/objects/quests/MineQuest.java @@ -13,6 +13,8 @@ import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; import org.bukkit.block.Block; +import org.bukkit.block.data.BlockData; +import org.bukkit.block.data.Ageable; import org.bukkit.entity.Player; import org.bukkit.inventory.PlayerInventory; @@ -25,8 +27,8 @@ public class MineQuest extends Quest { private final MineQuestObject mineQuestObject; - public MineQuest(UUID uuid) { - super(uuid, 0, 0, + public MineQuest(Player player) throws Exception { + super(player, 0, 0, QuestsConfig.MINE_QUESTS.get(Utilities.randomOr0(QuestsConfig.MINE_QUESTS.size() - 1)), -1, false); if (getVariant() instanceof MineQuestObject mineQuestObject) this.mineQuestObject = mineQuestObject; @@ -38,8 +40,8 @@ public class MineQuest extends Quest { } } - public MineQuest(UUID uuid, int mined, int turnedIn, String variant, int amount, boolean rewardReceived) { - super(uuid, mined, turnedIn, QuestsConfig.MINE_QUESTS.stream() + public MineQuest(Player player, int mined, int turnedIn, String variant, int amount, boolean rewardReceived) throws Exception { + super(player, mined, turnedIn, QuestsConfig.MINE_QUESTS.stream() .filter(object -> variant.equals(object.getInternalName())) .findAny().orElse(null), amount, rewardReceived); @@ -91,7 +93,7 @@ public class MineQuest extends Quest { @Override public TagResolver getTagResolvers() { TagResolver resolver = TagResolver.resolver( - Placeholder.unparsed("block", Utilities.formatName(mineQuestObject.getMaterial().name())), + Placeholder.unparsed("block", Utilities.formatName(mineQuestObject.getTurnInMaterial().name())), Placeholder.parsed("step_1_progress", getStep1() == getAmount() ? "" + getStep1() + "" : "" + getStep1() + ""), Placeholder.parsed("step_1_total", String.valueOf(getAmount())), @@ -121,7 +123,7 @@ public class MineQuest extends Quest { Arrays.stream(inventory.getContents()) .filter(Objects::nonNull) - .filter(itemStack -> itemStack.getType().equals(mineQuestObject.getMaterial())) + .filter(itemStack -> itemStack.getType().equals(mineQuestObject.getTurnInMaterial())) .forEach(itemStack -> { if (ref.tmpAmount == 0) return; @@ -149,8 +151,23 @@ public class MineQuest extends Quest { return QuestsConfig.MINE_COMMANDS; } + public boolean checkBlock(Block block) { + + BlockData blockData = block.getBlockData(); + + if (!block.getType().equals(mineQuestObject.getMaterial())) { + return true; + } + else if (blockData instanceof Ageable) { + Ageable ageable = (Ageable) blockData; + if (ageable.getAge() != ageable.getMaximumAge()) { + return true; + } + } + return false; + } public void mine(Block block) { - if (isDone() || !block.getType().equals(mineQuestObject.getMaterial()) || getAmount() == getStep1()) + if (isDone() || checkBlock(block) || getAmount() == getStep1()) return; addStep1(1); checkDone(); diff --git a/src/main/java/com/alttd/altitudequests/objects/quests/OtherQuest.java b/src/main/java/com/alttd/altitudequests/objects/quests/OtherQuest.java new file mode 100644 index 0000000..0a5de0f --- /dev/null +++ b/src/main/java/com/alttd/altitudequests/objects/quests/OtherQuest.java @@ -0,0 +1,218 @@ +package com.alttd.altitudequests.objects.quests; + +import com.alttd.altitudequests.config.Config; +import com.alttd.altitudequests.config.QuestsConfig; +import com.alttd.altitudequests.database.Database; +import com.alttd.altitudequests.objects.Quest; +import com.alttd.altitudequests.objects.Variant; +import com.alttd.altitudequests.objects.variants.OtherQuestObject; +import com.alttd.altitudequests.util.Logger; +import com.alttd.altitudequests.util.Utilities; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; +import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; +import org.bukkit.DyeColor; +import org.bukkit.Material; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.entity.Sheep; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.PlayerInventory; + +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +public class OtherQuest extends Quest { + + private final OtherQuestObject otherQuestObject; + + public OtherQuest(Player player) throws Exception { + super(player, 0, 0, + QuestsConfig.OTHER_QUEST.get(Utilities.randomOr0(QuestsConfig.OTHER_QUEST.size() - 1)), -1, false); + if (getVariant() instanceof OtherQuestObject otherQuestObject) + this.otherQuestObject = otherQuestObject; + else + this.otherQuestObject = null; + if (otherQuestObject == null) { + Logger.warning("Tried to create OtherQuest but unable to find variant: %.", "unknown"); + } + } + + public OtherQuest(Player player, int step1, int step2, String variant, int amount, boolean rewardReceived) throws Exception { + super(player, step1, step2, QuestsConfig.OTHER_QUEST.stream() + .filter(object -> variant.equals(object.getInternalName())) + .findAny().orElse(null), amount, rewardReceived); + if (getVariant() instanceof OtherQuestObject otherQuestObject) + this.otherQuestObject = otherQuestObject; + else + this.otherQuestObject = null; + if (otherQuestObject == null) { + Logger.warning("Tried to create OtherQuest but unable to find variant: %.", variant); + Logger.warning("Possible variants: %", QuestsConfig.OTHER_QUEST.stream().map(Variant::getInternalName).collect(Collectors.joining(", "))); + return; + } + checkDone(); + } + + @Override + public void save() { + String sql = "INSERT INTO generic_quest_progress " + + "(year_day, uuid, quest, quest_variant, step_1_progress, step_2_progress, amount, reward_received) " + + "VALUES (?, ?, ?, ?, ?, ?, ?, ?) " + + "ON DUPLICATE KEY UPDATE " + + "quest = ?, quest_variant = ?, step_1_progress = ?, step_2_progress = ?, year_day = ?, amount = ?, reward_received = ?"; + try { + PreparedStatement statement = Database.getDatabase().getConnection().prepareStatement(sql); + int yearDay = Utilities.getYearDay(); + if (Config.DEBUG) + Logger.info("Saving user for year day %.", String.valueOf(yearDay)); + statement.setInt(1, yearDay); + statement.setString(2, getUuid().toString()); + statement.setString(3, this.getClass().getSimpleName()); + statement.setString(4, otherQuestObject.getInternalName()); + statement.setInt(5, getStep1()); + statement.setInt(6, getStep2()); + statement.setInt(7, getAmount()); + statement.setInt(8, isRewardReceived() ? 1 : 0); + statement.setString(9, this.getClass().getSimpleName()); + statement.setString(10, otherQuestObject.getInternalName()); + statement.setInt(11, getStep1()); + statement.setInt(12, getStep2()); + statement.setInt(13, yearDay); + statement.setInt(14, getAmount()); + statement.setInt(15, isRewardReceived() ? 1 : 0); + statement.execute(); + } catch (SQLException exception) { + exception.printStackTrace(); + } + } + + @Override + public TagResolver getTagResolvers() { + TagResolver resolver = TagResolver.resolver( + Placeholder.unparsed("item", Utilities.formatName(otherQuestObject.getMaterial().name())), + Placeholder.parsed("step_1_progress", getStep1() == getAmount() ? + "" + getStep1() + "" : "" + getStep1() + ""), + Placeholder.parsed("step_1_total", String.valueOf(getAmount())), + Placeholder.parsed("step_2_progress", getStep2() == getAmount() ? + "" + getStep2() + "" : "" + getStep2() + ""), + Placeholder.parsed("step_2_total", String.valueOf(getAmount())), + Placeholder.unparsed("step_1", otherQuestObject.getStep1()), + Placeholder.unparsed("step_2", otherQuestObject.getStep2()), + Placeholder.unparsed("turn_in_text", QuestsConfig.OTHER_TURN_IN) + ); + Component turnInText = MiniMessage.miniMessage().deserialize(QuestsConfig.OTHER_TURN_IN, resolver); + return TagResolver.resolver( + resolver, + Placeholder.component("turn_in_text", turnInText) + ); + } + + @Override + public int turnIn(Player player) { + PlayerInventory inventory = player.getInventory(); + int maxToTurnIn = getMaxToTurnIn(); + + if (maxToTurnIn == 0) + return 0; + var ref = new Object() { + int tmpAmount = maxToTurnIn; + }; + + Arrays.stream(inventory.getContents()) + .filter(Objects::nonNull) + .filter(itemStack -> itemStack.getType().equals(otherQuestObject.getMaterial())) + .forEach(itemStack -> { + if (ref.tmpAmount == 0) + return; + if (itemStack.getAmount() > ref.tmpAmount) { + itemStack.setAmount(itemStack.getAmount() - ref.tmpAmount); + ref.tmpAmount = 0; + } else { + ref.tmpAmount -= itemStack.getAmount(); + itemStack.setAmount(0); + } + }); + int totalTurnedIn = maxToTurnIn - ref.tmpAmount; + addStep2(totalTurnedIn); + checkDone(player); + return totalTurnedIn; + } + + @Override + public Component getDisplayName() { + return MiniMessage.miniMessage().deserialize("%s".formatted(otherQuestObject.getCategory())); + } + + @Override + public List getRewardCommand() { + return QuestsConfig.COLLECT_DROPS_COMMANDS; + } + + public void fish(ItemStack caughtItem) { + if (isDone() || !caughtItem.getType().equals(otherQuestObject.getMaterial()) || getAmount() == getStep1()|| !otherQuestObject.getCategory().equalsIgnoreCase("FISHING")) { + return; + } + addStep1(1); + checkDone(); + } + + public void shear(Entity entity) { + if (isDone() || !entity.getType().equals(otherQuestObject.getEntity()) || getAmount() == getStep1()|| !otherQuestObject.getCategory().equalsIgnoreCase("SHEARING")) { + return; + } + DyeColor color = getDyeColorFromItemStack(otherQuestObject.getMaterial()); + if (entity instanceof Sheep sheep) { + if (sheep.getColor() != color) { + return; + } + } + addStep1(1); + checkDone(); + } + + public void bucket(ItemStack bucket, Entity entity) { + if (isDone() || !entity.getType().equals(otherQuestObject.getEntity()) || getAmount() == getStep1()|| !otherQuestObject.getCategory().equalsIgnoreCase("BUCKETING")) { + return; + } + addStep1(1); + checkDone(); + } + + public void raid() { + if (isDone() || getAmount() == getStep1() || !otherQuestObject.getCategory().equalsIgnoreCase("RAID")) { //without checking the category, other players who have otherQuests active will also have a step added + return; + } + addStep1(1); + checkDone(); + } + + //public void brewingStarted(ItemStack ingredient, Location brewingStandLocation){ + // Logger.warning("Brewing Started"); + //} + + //public void brewingFinished(List results, Location brewingStandLocation) { + // Logger.warning("Brewing Finished"); + //} + + public static List getSubTypes() { + return QuestsConfig.OTHER_QUEST.stream().map(Variant::getInternalName).collect(Collectors.toList()); + } + + public static DyeColor getDyeColorFromItemStack(Material material) { + if (material != null && material.name().contains("_WOOL")) { + String colorName = material.name().replace("_WOOL", ""); + try { + return DyeColor.valueOf(colorName); + } catch (IllegalArgumentException ignored) { + } + } + return null; + } +} + diff --git a/src/main/java/com/alttd/altitudequests/objects/variants/MineQuestObject.java b/src/main/java/com/alttd/altitudequests/objects/variants/MineQuestObject.java index 273542d..8301fae 100644 --- a/src/main/java/com/alttd/altitudequests/objects/variants/MineQuestObject.java +++ b/src/main/java/com/alttd/altitudequests/objects/variants/MineQuestObject.java @@ -8,14 +8,19 @@ import java.util.List; public class MineQuestObject extends Variant { private final Material material; + private final Material turnInMaterial; - public MineQuestObject(String internalName, String name, Material material, + public MineQuestObject(String internalName, String name, Material material, Material turnInMaterial, List questPages, List donePages, int min, int max) { super(internalName, name, questPages, donePages, min, max); this.material = material; + this.turnInMaterial = turnInMaterial; } public Material getMaterial() { return material; } + public Material getTurnInMaterial() { + return turnInMaterial; + } } diff --git a/src/main/java/com/alttd/altitudequests/objects/variants/OtherQuestObject.java b/src/main/java/com/alttd/altitudequests/objects/variants/OtherQuestObject.java new file mode 100644 index 0000000..e978af5 --- /dev/null +++ b/src/main/java/com/alttd/altitudequests/objects/variants/OtherQuestObject.java @@ -0,0 +1,34 @@ +package com.alttd.altitudequests.objects.variants; + +import com.alttd.altitudequests.objects.Variant; +import org.bukkit.Material; +import org.bukkit.entity.EntityType; + +import java.util.List; + +public class OtherQuestObject extends Variant { + + private final Material material; + private final EntityType entity; + private final String step1; + private final String step2; + private final String category; + + public OtherQuestObject(String internalName, String name, String category, Material item, EntityType entity, + List questPages, List donePages, int min, int max, String step1, String step2) { + super(internalName, name, questPages, donePages, min, max); + this.material = item; + this.entity = entity; + this.step1 = step1; + this.step2 = step2; + this.category = category; + } + + public Material getMaterial() { + return material; + } + public EntityType getEntity() {return entity;} + public String getStep1() {return step1;} + public String getStep2() {return step2;} + public String getCategory() {return category;} +} diff --git a/src/main/java/com/alttd/altitudequests/util/AutoHideBossBar.java b/src/main/java/com/alttd/altitudequests/util/AutoHideBossBar.java new file mode 100644 index 0000000..0d790d0 --- /dev/null +++ b/src/main/java/com/alttd/altitudequests/util/AutoHideBossBar.java @@ -0,0 +1,58 @@ +package com.alttd.altitudequests.util; + +import com.alttd.altitudequests.AQuest; +import com.alttd.altitudequests.config.Config; +import com.alttd.altitudequests.objects.Variant; +import org.bukkit.Bukkit; +import org.bukkit.NamespacedKey; +import org.bukkit.boss.BarColor; +import org.bukkit.boss.BarStyle; +import org.bukkit.boss.BossBar; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; + +import java.time.Instant; +import java.util.HashMap; + +public class AutoHideBossBar { + + private static final HashMap bossBars = new HashMap<>(); + + private final BossBar bossBar; + + public AutoHideBossBar(Player player, Variant variant, String part, String title, BarColor barColor) throws Exception { + NamespacedKey namespacedKeyOne = NamespacedKey.fromString(player.getUniqueId() + variant.getInternalName().toLowerCase() + part, AQuest.getInstance()); + if (namespacedKeyOne == null) { + Logger.warning("Unable to create nameSpacedKey with suffix % for quest for %", part, player.getName()); + throw new Exception("Failed to create namespace key"); + } + this.bossBar = Bukkit.createBossBar( + namespacedKeyOne, + title, + barColor, + BarStyle.SOLID); + bossBar.setVisible(false); + bossBar.addPlayer(player); + } + + public void show(double progress) { + bossBar.setVisible(true); + bossBar.setProgress(progress); + bossBars.put(bossBar, Instant.now().plusSeconds(Config.BOSS_BAR_AUTO_HIDE.toSeconds())); + } + + public static void initiate() { + new BukkitRunnable() { + @Override + public void run() { + for (HashMap.Entry entry : bossBars.entrySet()) { + if (Instant.now().isAfter(entry.getValue())) { + BossBar bossBar = entry.getKey(); + bossBar.setVisible(false); + bossBars.remove(entry.getKey()); + } + } + } + }.runTaskTimer(AQuest.getInstance(), 10, 10); + } +} diff --git a/src/main/java/com/alttd/altitudequests/util/ProgressBookOpener.java b/src/main/java/com/alttd/altitudequests/util/ProgressBookOpener.java new file mode 100644 index 0000000..e86a983 --- /dev/null +++ b/src/main/java/com/alttd/altitudequests/util/ProgressBookOpener.java @@ -0,0 +1,49 @@ +package com.alttd.altitudequests.util; + +import com.alttd.altitudequests.config.Config; +import com.alttd.altitudequests.objects.Quest; +import net.kyori.adventure.inventory.Book; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; +import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +public class ProgressBookOpener { + + private static final MiniMessage miniMessage = MiniMessage.miniMessage(); + + public static void openProgressBook(Player player) { + player.openBook(getProgressBook(player)); + } + + private static Book getProgressBook (Player player) { + return Book.builder() + .author(miniMessage.deserialize(Config.PROGRESS_BOOK_AUTHOR)) + .title(miniMessage.deserialize(Config.PROGRESS_BOOK_TITLE)) + .pages(getPages(player)) + .build(); + } + + private static final Component error = MiniMessage.miniMessage().deserialize("Error retrieving quest data"); + private static List getPages(Player player) { + Quest dailyQuest = Quest.getDailyQuest(player.getUniqueId()); + if (dailyQuest == null) + return List.of(error); + TagResolver tagResolver = TagResolver.resolver( + TagResolver.resolver(Placeholder.component("player", player.name())), + TagResolver.resolver(Placeholder.component("quest", dailyQuest.getDisplayName())), + TagResolver.resolver(Placeholder.component("variant", dailyQuest.getVariant().getName())), + dailyQuest.getTagResolvers() + ); + List pages = new ArrayList<>(); + pages.addAll(Config.PROGRESS_PAGES); + return (pages.stream() + .map(page -> miniMessage.deserialize(page, tagResolver)) + .collect(Collectors.toList())); + } +} \ No newline at end of file