diff --git a/README.md b/README.md index ec4d09b8..f765ec77 100644 --- a/README.md +++ b/README.md @@ -12,13 +12,7 @@ What is **BeautyQuests**? * BeautyQuests is a Minecraft quest plugin based on a simple-to-use graphical interface. * It's an absolutely free plugin with a full technical documentation. * It's also a collaborative work, where everyone can improve and add new features. If you have ideas, submit them and I or somebody else will try to implement them. -* It's compatible with a large number of other plugins (like MythicMobs, Jobs, Vault, ...). - -*** - -## Overview -BeautyQuests is a plugin that allows you to create and manage quests very easy with a GUI created with the in-game inventories. -This plugin is elaborate to look pretty and to simplify the quests for the players. +* It's compatible with a large number of other plugins (like MythicMobs, Jobs, Citizens, ...). *** @@ -27,18 +21,12 @@ Plugin releases can be downloaded from **[SpigotMC](https://www.spigotmc.org/res Development builds are available on **[Jenkins](https://ci.codemc.org/job/SkytAsul/job/BeautyQuests/)**. -*** - ## Wiki -You can find the **wiki [here](https://github.com/SkytAsul/BeautyQuests/wiki)**. - -*** +You can find the **wiki [here](https://github.com/SkytAsul/BeautyQuests/wiki)**. It contains a lot of useful informations. ## Crowdin If you want to help us translate BeautyQuests into your native language, join the [official BeautyQuests Crowdin project](https://crowdin.com/project/beautyquests) and let players in-game see your translations (read the project description for more informations). -*** - ## Discord If you need help, found a bug, or want to share an idea, you can join the official [Plugin Support Discord server by SkytAsul](https://discord.gg/H8fXrkD). diff --git a/api/pom.xml b/api/pom.xml index cf6b79e9..ed5c1e60 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -156,7 +156,7 @@ com.github.cryptomorin XSeries - 9.10.0 + 11.2.0 diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/ItemUtils.java b/api/src/main/java/fr/skytasul/quests/api/gui/ItemUtils.java index d7d9dae8..f341b8f6 100644 --- a/api/src/main/java/fr/skytasul/quests/api/gui/ItemUtils.java +++ b/api/src/main/java/fr/skytasul/quests/api/gui/ItemUtils.java @@ -1,5 +1,6 @@ package fr.skytasul.quests.api.gui; +import com.cryptomorin.xseries.XEnchantment; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.options.QuestOption; @@ -40,6 +41,8 @@ public static ItemStack item(XMaterial type, String name, String... lore) { .warning("Trying to create an item for an unsupported material " + type.name()); type = XMaterial.SPONGE; } + if (MinecraftVersion.MAJOR >= 13 && !type.parseMaterial().isItem()) + type = XMaterial.SPONGE; ItemStack is = type.parseItem(); ItemMeta im = is.getItemMeta(); addSpecificFlags(im, is.getType()); @@ -60,6 +63,8 @@ public static ItemStack item(XMaterial type, String name, List lore) { .warning("Trying to create an item for an unsupported material " + type.name()); type = XMaterial.SPONGE; } + if (MinecraftVersion.MAJOR >= 13 && !type.parseMaterial().isItem()) + type = XMaterial.SPONGE; ItemStack is = type.parseItem(); ItemMeta im = is.getItemMeta(); addSpecificFlags(im, is.getType()); @@ -339,10 +344,11 @@ public static void setGlittering(ItemStack is, boolean glitter) { if (MinecraftVersion.isHigherThan(20, 6)) { im.setEnchantmentGlintOverride(glitter ? Boolean.TRUE : null); } else { - if (glitter) - im.addEnchant(Enchantment.getByName("DURABILITY"), 0, true); - else - im.removeEnchant(Enchantment.getByName("DURABILITY")); + if (glitter) { + im.addEnchant(XEnchantment.UNBREAKING.getEnchant(), 0, true); + im.addItemFlags(ItemFlag.HIDE_ENCHANTS); + } else + im.removeEnchant(XEnchantment.UNBREAKING.getEnchant()); } is.setItemMeta(im); } diff --git a/api/src/main/java/fr/skytasul/quests/api/localization/Lang.java b/api/src/main/java/fr/skytasul/quests/api/localization/Lang.java index c2aee23a..06f8f44c 100644 --- a/api/src/main/java/fr/skytasul/quests/api/localization/Lang.java +++ b/api/src/main/java/fr/skytasul/quests/api/localization/Lang.java @@ -1,9 +1,9 @@ package fr.skytasul.quests.api.localization; -import java.util.Objects; +import fr.skytasul.quests.api.utils.messaging.MessageType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import fr.skytasul.quests.api.utils.messaging.MessageType; +import java.util.Objects; /** * Stores all string paths and methods to format and send them to players. @@ -134,6 +134,7 @@ public enum Lang implements Locale { POOL_RESET_FULL("msg.command.resetPlayerPool.full"), // 0: pool ID, 1: player POOL_START_ERROR("msg.command.startPlayerPool.error", ErrorPrefix), // 0: pool ID, 1: player POOL_START_SUCCESS("msg.command.startPlayerPool.success", SuccessPrefix), // 0: pool ID, 1: player, 2: result + POOL_COMPLETELY_RESET("msg.command.resetPool", SuccessPrefix), // 0: amount of players COMMAND_SCOREBOARD_LINESET("msg.command.scoreboard.lineSet"), // 0: line id COMMAND_SCOREBOARD_LINERESET("msg.command.scoreboard.lineReset"), // 0: line id diff --git a/api/src/main/java/fr/skytasul/quests/api/pools/QuestPool.java b/api/src/main/java/fr/skytasul/quests/api/pools/QuestPool.java index 6c5f884c..26497f02 100644 --- a/api/src/main/java/fr/skytasul/quests/api/pools/QuestPool.java +++ b/api/src/main/java/fr/skytasul/quests/api/pools/QuestPool.java @@ -1,16 +1,15 @@ package fr.skytasul.quests.api.pools; -import java.util.List; -import java.util.concurrent.CompletableFuture; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.api.players.PlayerAccount; -import fr.skytasul.quests.api.players.PlayerPoolDatas; import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.requirements.RequirementList; import fr.skytasul.quests.api.utils.messaging.HasPlaceholders; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import java.util.List; +import java.util.concurrent.CompletableFuture; public interface QuestPool extends HasPlaceholders { @@ -46,7 +45,7 @@ public interface QuestPool extends HasPlaceholders { ItemStack getItemStack(@NotNull String action); @NotNull - CompletableFuture resetPlayer(@NotNull PlayerAccount acc); + CompletableFuture resetPlayer(@NotNull PlayerAccount acc); void resetPlayerTimer(@NotNull PlayerAccount acc); diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/types/Dialogable.java b/api/src/main/java/fr/skytasul/quests/api/stages/types/Dialogable.java index 6bfceabd..0bf264c2 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/types/Dialogable.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/types/Dialogable.java @@ -1,23 +1,32 @@ package fr.skytasul.quests.api.stages.types; -import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.api.npcs.BqNpc; import fr.skytasul.quests.api.npcs.dialogs.Dialog; import fr.skytasul.quests.api.npcs.dialogs.DialogRunner; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public interface Dialogable { - + @Nullable Dialog getDialog(); - + @Nullable DialogRunner getDialogRunner(); - + @Nullable BqNpc getNPC(); - + default boolean hasDialog() { return getNPC() != null && getDialog() != null && !getDialog().getMessages().isEmpty(); } - + + default @NotNull String getNpcName() { + if (getNPC() == null) + return "§c§lunknown NPC"; + if (getDialog() != null && getDialog().getNpcName() != null) + return getDialog().getNpcName(); + return getNPC().getNpc().getName(); + } + } diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/MinecraftNames.java b/api/src/main/java/fr/skytasul/quests/api/utils/MinecraftNames.java index b336f138..120020cb 100644 --- a/api/src/main/java/fr/skytasul/quests/api/utils/MinecraftNames.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/MinecraftNames.java @@ -12,7 +12,8 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; -import java.util.*; +import java.util.HashMap; +import java.util.Map; import java.util.Map.Entry; public class MinecraftNames { @@ -24,6 +25,8 @@ public class MinecraftNames { private static Map cachedEntities = new HashMap<>(); private static Map cachedMaterials = new HashMap<>(); + private static final boolean POTIONS_ENABLED = MinecraftVersion.isHigherThan(20, 5); + public static boolean intialize(@NotNull Path path) { try { if (!Files.exists(path)) { @@ -44,16 +47,19 @@ public static boolean intialize(@NotNull Path path) { }else if (key.startsWith("item.minecraft.")) { String item = key.substring(15); if (item.startsWith("potion.effect.")) { - PotionMapping.matchFromTranslationKey(item.substring(14)) - .forEachRemaining(potion -> potion.setNormalName(value)); - }else if (item.startsWith("splash_potion.effect.")) { - PotionMapping.matchFromTranslationKey(item.substring(21)) + if (POTIONS_ENABLED) + PotionMapping.matchFromTranslationKey(item.substring(14)) + .forEachRemaining(potion -> potion.setNormalName(value)); + } else if (item.startsWith("splash_potion.effect.")) { + if (POTIONS_ENABLED) + PotionMapping.matchFromTranslationKey(item.substring(21)) .forEachRemaining(potion -> potion.setSplashName(value)); - }else if (item.startsWith("lingering_potion.effect.")) { - PotionMapping.matchFromTranslationKey(item.substring(24)) + } else if (item.startsWith("lingering_potion.effect.")) { + if (POTIONS_ENABLED) + PotionMapping.matchFromTranslationKey(item.substring(24)) .forEachRemaining(potion -> potion.setLingeringName(value)); } else - cachedMaterials.put(XMaterial.matchXMaterial(item).orElse(null), value); + XMaterial.matchXMaterial(item).ifPresent(material -> cachedMaterials.put(material, value)); } } }catch (Exception e) { @@ -77,7 +83,7 @@ public static boolean intialize(@NotNull Path path) { public static @NotNull String getMaterialName(ItemStack item) { XMaterial type = XMaterial.matchXMaterial(item); - if (MinecraftVersion.isHigherThan(20, 2) + if (POTIONS_ENABLED && (type == XMaterial.POTION || type == XMaterial.LINGERING_POTION || type == XMaterial.SPLASH_POTION)) { PotionMeta meta = (PotionMeta) item.getItemMeta(); if (meta.getBasePotionType() != null) diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/PlayerListCategory.java b/api/src/main/java/fr/skytasul/quests/api/utils/PlayerListCategory.java index 5eb2a1ab..04774576 100644 --- a/api/src/main/java/fr/skytasul/quests/api/utils/PlayerListCategory.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/PlayerListCategory.java @@ -3,7 +3,9 @@ import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.localization.Locale; import org.bukkit.DyeColor; +import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -11,48 +13,48 @@ public enum PlayerListCategory { FINISHED( 1, - XMaterial.BOOK, - Lang.finisheds.toString(), - DyeColor.GREEN), + Lang.finisheds), IN_PROGRESS( 2, - XMaterial.WRITABLE_BOOK, - Lang.inProgress.toString(), - DyeColor.YELLOW), + Lang.inProgress), NOT_STARTED( 3, - XMaterial.PAPER, - Lang.notStarteds.toString(), - DyeColor.RED); + Lang.notStarteds); private final int slot; - private final @NotNull XMaterial material; - private final @NotNull String name; - private final @Nullable DyeColor color; + private final @NotNull Locale name; + private @NotNull ItemStack icon = XMaterial.BARRIER.parseItem(); + private @Nullable DyeColor color = DyeColor.RED; - private PlayerListCategory(int slot, @NotNull XMaterial material, @NotNull String name, @Nullable DyeColor color) { + private PlayerListCategory(int slot, @NotNull Locale name) { this.slot = slot; - this.material = material; this.name = name; - this.color = color; } public int getSlot() { return slot; } - public @NotNull XMaterial getMaterial() { - return material; + public @NotNull String getName() { + return name.getValue(); } - public @NotNull String getName() { - return name; + public @NotNull ItemStack getIcon() { + return icon; + } + + public void setIcon(@NotNull ItemStack icon) { + this.icon = icon; } public @Nullable DyeColor getColor() { return color; } + public void setColor(@NotNull DyeColor color) { + this.color = color; + } + public boolean isEnabled() { return QuestsConfiguration.getConfig().getQuestsMenuConfig().getEnabledTabs().contains(this); } diff --git a/core/pom.xml b/core/pom.xml index 2818467b..7ce3072a 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -82,7 +82,7 @@ jeff-media-public - https://hub.jeff-media.com/nexus/repository/jeff-media-public/ + https://repo.jeff-media.com/public/ codemc-repo @@ -170,7 +170,7 @@ com.jeff_media SpigotUpdateChecker - 3.0.0 + 3.0.3 compile diff --git a/core/src/main/java/fr/skytasul/quests/BeautyQuests.java b/core/src/main/java/fr/skytasul/quests/BeautyQuests.java index bcdbeb48..410cea75 100644 --- a/core/src/main/java/fr/skytasul/quests/BeautyQuests.java +++ b/core/src/main/java/fr/skytasul/quests/BeautyQuests.java @@ -1,35 +1,5 @@ package fr.skytasul.quests; -import java.io.File; -import java.io.IOException; -import java.lang.reflect.Method; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; -import java.util.logging.Level; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import org.bstats.bukkit.Metrics; -import org.bstats.charts.DrilldownPie; -import org.bstats.charts.SimplePie; -import org.bstats.charts.SingleLineChart; -import org.bukkit.Bukkit; -import org.bukkit.command.CommandSender; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.entity.Player; -import org.bukkit.plugin.Plugin; -import org.bukkit.plugin.java.JavaPlugin; -import org.bukkit.scheduler.BukkitRunnable; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import com.jeff_media.updatechecker.UpdateCheckSource; import com.jeff_media.updatechecker.UpdateChecker; import com.tchristofferson.configupdater.ConfigUpdater; @@ -60,6 +30,36 @@ import fr.skytasul.quests.utils.compatibility.Post1_16; import fr.skytasul.quests.utils.logger.LoggerHandler; import fr.skytasul.quests.utils.nms.NMS; +import org.bstats.bukkit.Metrics; +import org.bstats.charts.DrilldownPie; +import org.bstats.charts.SimplePie; +import org.bstats.charts.SingleLineChart; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.scheduler.BukkitRunnable; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Method; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Level; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; public class BeautyQuests extends JavaPlugin implements QuestsPlugin { @@ -366,6 +366,7 @@ private void launchUpdateChecker(String pluginVersion) { .setDonationLink("https://paypal.me/SkytAsul") .setSupportLink("https://discord.gg/H8fXrkD") .setNotifyOpsOnJoin(false) + .setColoredConsoleOutput(true) .checkNow(); } diff --git a/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java b/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java index 5acfb462..f043fb7e 100644 --- a/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java @@ -654,11 +654,28 @@ private boolean update() { result |= migrateEntry(config.getParent(), "menuOpenNotStartedTabWhenEmpty", config, "openNotStartedTabWhenEmpty"); result |= migrateEntry(config.getParent(), "allowPlayerCancelQuest", config, "allowPlayerCancelQuest"); } + if (config.contains("enabledTabs")) { + Set tabs = config.getStringList("enabledTabs").stream() + .map(PlayerListCategory::fromString).collect(Collectors.toSet()); + for (PlayerListCategory cat : PlayerListCategory.values()) { + config.set("tabs." + cat.name().toLowerCase().replace('_', ' ') + ".enabled", tabs.contains(cat)); + } + result = true; + } return result; } private void init() { - tabs = config.getStringList("enabledTabs").stream().map(PlayerListCategory::fromString).collect(Collectors.toSet()); + tabs = EnumSet.noneOf(PlayerListCategory.class); + for (PlayerListCategory cat : PlayerListCategory.values()) { + ConfigurationSection catConfig = + config.getConfigurationSection("tabs." + cat.name().toLowerCase().replace('_', ' ')); + cat.setIcon(loadItem(catConfig, "icon", XMaterial.BARRIER.parseItem())); + cat.setColor(DyeColor.valueOf(catConfig.getString("color").toUpperCase())); + if (catConfig.getBoolean("enabled")) + tabs.add(cat); + } + if (tabs.isEmpty()) { QuestsPlugin.getPlugin().getLoggerExpanded().warning("Quests Menu must have at least one enabled tab."); tabs = EnumSet.allOf(PlayerListCategory.class); diff --git a/core/src/main/java/fr/skytasul/quests/commands/CommandsManagerImplementation.java b/core/src/main/java/fr/skytasul/quests/commands/CommandsManagerImplementation.java index 275bdd31..9473a880 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsManagerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsManagerImplementation.java @@ -1,11 +1,5 @@ package fr.skytasul.quests.commands; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Unmodifiable; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.QuestsPlugin; @@ -26,6 +20,12 @@ import fr.skytasul.quests.api.utils.messaging.MessageType; import fr.skytasul.quests.api.utils.messaging.MessageUtils; import fr.skytasul.quests.scoreboards.Scoreboard; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Unmodifiable; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; public class CommandsManagerImplementation implements CommandsManager { diff --git a/core/src/main/java/fr/skytasul/quests/commands/CommandsPlayerManagement.java b/core/src/main/java/fr/skytasul/quests/commands/CommandsPlayerManagement.java index 9e1828a1..0bbad9a3 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsPlayerManagement.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsPlayerManagement.java @@ -292,6 +292,42 @@ public void resetQuest(BukkitCommandActor actor, Quest quest) { } + @Subcommand("resetPool") + @CommandPermission("beautyquests.command.resetQuest") + public void resetPool(BukkitCommandActor actor, QuestPool pool) { + List> futures = new ArrayList<>(Bukkit.getOnlinePlayers().size()); + + for (Player p : Bukkit.getOnlinePlayers()) { + futures.add(pool.resetPlayer(PlayersManager.getPlayerAccount(p)) + .whenComplete(QuestsPlugin.getPlugin().getLoggerExpanded().logError( + "An error occurred while resetting pool " + pool.getId() + " to player " + p.getName(), + actor.getSender()))); + } + + CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).whenComplete((__, ___) -> { + // we do not care about failure or success of this "global" future + + int resetAmount = + (int) futures.stream().filter(future -> { + try { + return !future.isCompletedExceptionally() && future.get(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } catch (ExecutionException ignored) { + // we already check if the future is completed exceptionnally before using get() + } + return false; + }).count(); + + BeautyQuests.getInstance().getPlayersManager().removePoolDatas(pool) + .whenComplete(QuestsPlugin.getPlugin().getLoggerExpanded().logError(removedAmount -> { + Lang.POOL_COMPLETELY_RESET.quickSend(actor.getSender(), "player_amount", + removedAmount + resetAmount); + }, "An error occurred while removing pool datas", actor.getSender())); + }).whenComplete(QuestsPlugin.getPlugin().getLoggerExpanded().logError()); + + } + @Subcommand ("seePlayer") @CommandPermission ("beautyquests.command.seePlayer") public void seePlayer(Player actor, Player player) { diff --git a/core/src/main/java/fr/skytasul/quests/commands/CommandsScoreboard.java b/core/src/main/java/fr/skytasul/quests/commands/CommandsScoreboard.java index 2f6c866a..06f6ab0a 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsScoreboard.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsScoreboard.java @@ -1,12 +1,12 @@ package fr.skytasul.quests.commands; -import org.bukkit.entity.Player; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.commands.revxrsal.annotation.Default; import fr.skytasul.quests.api.commands.revxrsal.annotation.Optional; import fr.skytasul.quests.api.commands.revxrsal.annotation.Range; import fr.skytasul.quests.api.commands.revxrsal.annotation.Subcommand; import fr.skytasul.quests.api.commands.revxrsal.bukkit.BukkitCommandActor; +import fr.skytasul.quests.api.commands.revxrsal.bukkit.EntitySelector; import fr.skytasul.quests.api.commands.revxrsal.bukkit.annotation.CommandPermission; import fr.skytasul.quests.api.commands.revxrsal.command.ExecutableCommand; import fr.skytasul.quests.api.commands.revxrsal.exception.InvalidSubcommandException; @@ -14,23 +14,26 @@ import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.scoreboards.Scoreboard; +import org.bukkit.entity.Player; public class CommandsScoreboard implements OrphanCommand { - + @Default @CommandPermission ("beautyquests.command.scoreboard.toggle") - public void scoreboardToggle(Player player, ExecutableCommand command, Scoreboard scoreboard, @Optional String subcommand) { + public void scoreboardToggle(BukkitCommandActor actor, ExecutableCommand command, @Optional String subcommand) { if (subcommand != null) throw new InvalidSubcommandException(command.getPath(), subcommand); + + Scoreboard scoreboard = BeautyQuests.getInstance().getScoreboardManager().getPlayerScoreboard(actor.requirePlayer()); if (scoreboard.isForceHidden()) { scoreboard.show(true); - Lang.COMMAND_SCOREBOARD_OWN_SHOWN.send(player); + Lang.COMMAND_SCOREBOARD_OWN_SHOWN.send(actor.getSender()); }else { scoreboard.hide(true); - Lang.COMMAND_SCOREBOARD_OWN_HIDDEN.send(player); + Lang.COMMAND_SCOREBOARD_OWN_HIDDEN.send(actor.getSender()); } } - + private PlaceholderRegistry getLineRegistry(int line) { return PlaceholderRegistry.of("line_id", line); } @@ -45,7 +48,7 @@ public void setline(BukkitCommandActor actor, Player player, Scoreboard scoreboa scoreboard.setCustomLine(line, text); Lang.COMMAND_SCOREBOARD_LINESET.send(actor.getSender(), getLineRegistry(line)); } - + @Subcommand ("removeline") @CommandPermission ("beautyquests.command.scoreboard") public void removeline(BukkitCommandActor actor, Player player, Scoreboard scoreboard, @Range (min = 0) int line) { @@ -54,7 +57,7 @@ public void removeline(BukkitCommandActor actor, Player player, Scoreboard score } else Lang.COMMAND_SCOREBOARD_LINENOEXIST.send(actor.getSender(), getLineRegistry(line)); } - + @Subcommand ("resetline") @CommandPermission ("beautyquests.command.scoreboard") public void resetline(BukkitCommandActor actor, Player player, Scoreboard scoreboard, @Range (min = 0) int line) { @@ -63,7 +66,7 @@ public void resetline(BukkitCommandActor actor, Player player, Scoreboard scoreb } else Lang.COMMAND_SCOREBOARD_LINENOEXIST.send(actor.getSender(), getLineRegistry(line)); } - + @Subcommand ("resetall") @CommandPermission ("beautyquests.command.scoreboard") public void resetall(BukkitCommandActor actor, Player player) { @@ -71,19 +74,25 @@ public void resetall(BukkitCommandActor actor, Player player) { BeautyQuests.getInstance().getScoreboardManager().create(player); Lang.COMMAND_SCOREBOARD_RESETALL.send(actor.getSender(), getPlayerRegistry(player)); } - + @Subcommand ("show") @CommandPermission ("beautyquests.command.scoreboard") - public void show(BukkitCommandActor actor, Player player, Scoreboard scoreboard) { - scoreboard.show(true); - Lang.COMMAND_SCOREBOARD_SHOWN.send(actor.getSender(), getPlayerRegistry(player)); + public void show(BukkitCommandActor actor, EntitySelector players) { + for (Player player : players) { + Scoreboard scoreboard = BeautyQuests.getInstance().getScoreboardManager().getPlayerScoreboard(player); + scoreboard.show(true); + Lang.COMMAND_SCOREBOARD_SHOWN.send(actor.getSender(), getPlayerRegistry(player)); + } } - + @Subcommand ("hide") @CommandPermission ("beautyquests.command.scoreboard") - public void hide(BukkitCommandActor actor, Player player, Scoreboard scoreboard) { - scoreboard.hide(true); - Lang.COMMAND_SCOREBOARD_HIDDEN.send(actor.getSender(), getPlayerRegistry(player)); + public void hide(BukkitCommandActor actor, EntitySelector players) { + for (Player player : players) { + Scoreboard scoreboard = BeautyQuests.getInstance().getScoreboardManager().getPlayerScoreboard(player); + scoreboard.hide(true); + Lang.COMMAND_SCOREBOARD_HIDDEN.send(actor.getSender(), getPlayerRegistry(player)); + } } - + } \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/gui/DefaultItemFactory.java b/core/src/main/java/fr/skytasul/quests/gui/DefaultItemFactory.java index 106d46be..c84d04d7 100755 --- a/core/src/main/java/fr/skytasul/quests/gui/DefaultItemFactory.java +++ b/core/src/main/java/fr/skytasul/quests/gui/DefaultItemFactory.java @@ -33,7 +33,7 @@ public class DefaultItemFactory implements ItemFactory { @Override public @NotNull ItemStack getDone() { - return addEnchant(item(XMaterial.DIAMOND, Lang.done.toString()), XEnchantment.DURABILITY.getEnchant(), 0); + return addEnchant(item(XMaterial.DIAMOND, Lang.done.toString()), XEnchantment.UNBREAKING.getEnchant(), 0); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/gui/blocks/SelectBlockGUI.java b/core/src/main/java/fr/skytasul/quests/gui/blocks/SelectBlockGUI.java index 69211605..b286c5fc 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/blocks/SelectBlockGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/blocks/SelectBlockGUI.java @@ -15,6 +15,7 @@ import fr.skytasul.quests.api.utils.MinecraftVersion; import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; +import fr.skytasul.quests.utils.compatibility.Post1_13; import fr.skytasul.quests.utils.nms.NMS; import org.bukkit.Bukkit; import org.bukkit.Material; @@ -56,18 +57,28 @@ public void click(@NotNull LayoutedClickEvent event) { @Override public void place(@NotNull Inventory inventory, int slot) { - inventory.setItem(slot, ItemUtils.item(type, Lang.materialName.quickFormat("block_type", type.name()))); - if (inventory.getItem(slot) == null || inventory.getItem(slot).getType() == Material.AIR) { - // means that the material cannot be treated as an inventory item (ie: fire) - inventory.setItem(slot, - ItemUtils.item(XMaterial.STONE, Lang.materialName.quickFormat("block_type", type.name()), - QuestOption.formatDescription( - Lang.materialNotItemLore.quickFormat("block_type", type.name())))); - } + XMaterial mat = type; + if (MinecraftVersion.MAJOR >= 13 && !Post1_13.isItem(type.parseMaterial())) + mat = XMaterial.STONE; + placeInternal(inventory, slot, mat); + if (tag == null) ItemUtils.setGlittering(inventory.getItem(slot), true); } + private void placeInternal(@NotNull Inventory inventory, int slot, @NotNull XMaterial material) { + ItemStack item = ItemUtils.item(material, Lang.materialName.quickFormat("block_type", type.name())); + if (material != type) + ItemUtils.lore(item, + QuestOption.formatDescription(Lang.materialNotItemLore.quickFormat("block_type", type.name()))); + + inventory.setItem(slot, item); + + item = inventory.getItem(slot); + if (item == null || item.getType() == Material.AIR) + placeInternal(inventory, slot, XMaterial.STONE); + } + }); if (MinecraftVersion.MAJOR >= 13) { buttons.put(5, LayoutedButton.create(() -> { diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/quest/QuestCreationGuiImplementation.java b/core/src/main/java/fr/skytasul/quests/gui/creation/quest/QuestCreationGuiImplementation.java index 0b5d85d5..e1aa5ea7 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/quest/QuestCreationGuiImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/quest/QuestCreationGuiImplementation.java @@ -1,15 +1,5 @@ package fr.skytasul.quests.gui.creation.quest; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.QuestsPlugin; @@ -44,6 +34,16 @@ import fr.skytasul.quests.structure.StageControllerImplementation; import fr.skytasul.quests.utils.QuestUtils; import net.md_5.bungee.api.ChatColor; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; public class QuestCreationGuiImplementation extends LayoutedGUI implements QuestCreationGui { @@ -51,9 +51,9 @@ public class QuestCreationGuiImplementation extends LayoutedGUI implements Quest private final UpdatableOptionSet options; private final int doneButtonSlot; - - private Boolean keepPlayerDatas = null; - + + private boolean keepPlayerDatas = true; + public QuestCreationGuiImplementation(QuestCreationSession session) { super(null, new HashMap<>(), StandardCloseBehavior.CONFIRM); // null name because it is computed in #instanciate @@ -98,7 +98,7 @@ public boolean isValid() { buttons.put(QuestOptionCreator.calculateSlot(3), LayoutedButton.create(QuestsPlugin.getPlugin().getGuiManager().getItemFactory().getPreviousPage(), event -> session.openStagesGUI(event.getPlayer()))); - + doneButtonSlot = QuestOptionCreator.calculateSlot(5); buttons.put(doneButtonSlot, LayoutedButton.create(() -> { boolean finishable = isFinishable(); @@ -117,6 +117,17 @@ public boolean isValid() { finish(event.getPlayer()); })); options.getWrapper(OptionName.class).dependent.add(() -> super.refresh(doneButtonSlot)); + + if (session.isEdition()) { + keepPlayerDatas = true; + int resetSlot = QuestOptionCreator.calculateSlot(6); + buttons.put(resetSlot, LayoutedButton.createSwitch(() -> keepPlayerDatas, Lang.keepDatas.toString(), + Arrays.asList(QuestOption.formatDescription(Lang.keepDatasLore.toString())), + event -> { + keepPlayerDatas = ItemUtils.toggleSwitch(event.getClicked()); + refresh(doneButtonSlot); + })); + } } @Override @@ -131,13 +142,6 @@ protected Inventory instanciate(@NotNull Player player) { return Bukkit.createInventory(null, (int) Math.ceil((QuestOptionCreator.getLastSlot() + 1) / 9D) * 9, invName); } - @Override - protected void refresh(@NotNull Player player, @NotNull Inventory inventory) { - super.refresh(player, inventory); - if (session.areStagesEdited() && keepPlayerDatas == null) - setStagesEdited(); - } - private boolean isFinishable() { return options.getOption(OptionName.class).getValue() != null; } @@ -153,7 +157,6 @@ public void updateOptionItem(@NotNull QuestOption option) { } private void finish(Player p) { - boolean keepPlayerDatas = Boolean.TRUE.equals(this.keepPlayerDatas); QuestImplementation qu; if (session.isEdition()) { QuestsPlugin.getPlugin().getLoggerExpanded().debug( @@ -175,7 +178,7 @@ private void finish(Player p) { id = BeautyQuests.getInstance().getQuestsManager().getFreeQuestID(); qu = new QuestImplementation(id); } - + for (QuestOption option : options) { if (option.hasCustomValue()) qu.addOption(option); } @@ -215,17 +218,17 @@ private void finish(Player p) { DefaultErrors.sendGeneric(p, "initial quest save"); QuestsPlugin.getPlugin().getLoggerExpanded().severe("Error when trying to save newly created quest.", e); } - + if (keepPlayerDatas) keepDatas(qu); - + QuestsAPI.getAPI().propagateQuestsHandlers(handler -> { if (session.isEdition()) handler.questEdit(qu, session.getQuestEdited(), keepPlayerDatas); else handler.questCreate(qu); }); } - + close(p); } @@ -244,7 +247,7 @@ private void keepDatas(QuestImplementation qu) { } } } - + private boolean loadBranch(Player p, QuestBranchImplementation branch, StagesGUI stagesGui) { boolean failure = false; for (StageCreationContextImplementation context : stagesGui.getStageCreations()) { @@ -277,17 +280,4 @@ public StageControllerImplementation createStage(St return controller; } - private void setStagesEdited() { - keepPlayerDatas = false; - refresh(doneButtonSlot); - int resetSlot = QuestOptionCreator.calculateSlot(6); - buttons.put(resetSlot, LayoutedButton.createSwitch(() -> keepPlayerDatas, Lang.keepDatas.toString(), - Arrays.asList(QuestOption.formatDescription(Lang.keepDatasLore.toString())), - event -> { - keepPlayerDatas = ItemUtils.toggleSwitch(event.getClicked()); - refresh(doneButtonSlot); - })); - refresh(resetSlot); - } - } \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/gui/quests/DialogHistoryGUI.java b/core/src/main/java/fr/skytasul/quests/gui/quests/DialogHistoryGUI.java index 994b4aaa..d0761577 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/quests/DialogHistoryGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/quests/DialogHistoryGUI.java @@ -164,7 +164,7 @@ public Page getCurrentPage() { public ItemStack setMeta(ItemStack item) { return ItemUtils.nameAndLore( item, - "§8" + objects.indexOf(this) + " (" + dialogable.getNPC().getNpc().getName() + "§8) - " + "§8" + objects.indexOf(this) + " (" + dialogable.getNpcName() + "§8) - " + getCurrentPage().header, getCurrentPage().lines); } diff --git a/core/src/main/java/fr/skytasul/quests/gui/quests/PlayerListGUI.java b/core/src/main/java/fr/skytasul/quests/gui/quests/PlayerListGUI.java index 14862332..44fe74d6 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/quests/PlayerListGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/quests/PlayerListGUI.java @@ -56,7 +56,7 @@ protected void populate(@NotNull Player player, @NotNull Inventory inventory) { for (PlayerListCategory enabledCat : QuestsConfiguration.getConfig().getQuestsMenuConfig().getEnabledTabs()) { setBarItem(enabledCat.getSlot(), - ItemUtils.item(enabledCat.getMaterial(), UNSELECTED_PREFIX + enabledCat.getName())); + ItemUtils.name(enabledCat.getIcon(), UNSELECTED_PREFIX + enabledCat.getName())); } if (PlayerListCategory.IN_PROGRESS.isEnabled()) { diff --git a/core/src/main/java/fr/skytasul/quests/mobs/BukkitEntityFactory.java b/core/src/main/java/fr/skytasul/quests/mobs/BukkitEntityFactory.java index 41b18aac..0f4a72d3 100644 --- a/core/src/main/java/fr/skytasul/quests/mobs/BukkitEntityFactory.java +++ b/core/src/main/java/fr/skytasul/quests/mobs/BukkitEntityFactory.java @@ -1,22 +1,23 @@ package fr.skytasul.quests.mobs; -import java.util.Arrays; -import java.util.List; -import java.util.function.Consumer; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.mobs.MobFactory; +import fr.skytasul.quests.api.utils.MinecraftNames; +import fr.skytasul.quests.api.utils.XMaterial; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.entity.EntityDeathEvent; import org.bukkit.inventory.ItemStack; -import fr.skytasul.quests.api.QuestsPlugin; -import fr.skytasul.quests.api.gui.ItemUtils; -import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.mobs.MobFactory; -import fr.skytasul.quests.api.utils.MinecraftNames; -import fr.skytasul.quests.api.utils.XMaterial; +import java.util.Arrays; +import java.util.List; +import java.util.function.Consumer; public class BukkitEntityFactory implements MobFactory, Listener { @@ -35,7 +36,7 @@ public ItemStack getFactoryItem() { public void itemClick(Player p, Consumer run) { QuestsPlugin.getPlugin().getGuiManager().getFactory().createEntityTypeSelection(run, x -> x != null).open(p); } - + @Override public boolean bukkitMobApplies(EntityType first, Entity entity) { return entity.getType() == first; @@ -60,13 +61,13 @@ public String getName(EntityType data) { public EntityType getEntityType(EntityType data) { return data; } - + @Override public List getDescriptiveLore(EntityType data) { return Arrays.asList(Lang.EntityType.quickFormat("entity_type", MinecraftNames.getEntityName(data))); } - @EventHandler + @EventHandler(priority = EventPriority.MONITOR) public void onEntityKilled(EntityDeathEvent e) { LivingEntity en = e.getEntity(); if (en.getKiller() == null) return; @@ -74,5 +75,5 @@ public void onEntityKilled(EntityDeathEvent e) { return; callEvent(e, en.getType(), en, en.getKiller()); } - + } diff --git a/core/src/main/java/fr/skytasul/quests/npcs/BqNpcImplementation.java b/core/src/main/java/fr/skytasul/quests/npcs/BqNpcImplementation.java index 45062a1d..68308515 100644 --- a/core/src/main/java/fr/skytasul/quests/npcs/BqNpcImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/npcs/BqNpcImplementation.java @@ -1,18 +1,5 @@ package fr.skytasul.quests.npcs; -import java.util.*; -import java.util.Map.Entry; -import java.util.function.Predicate; -import org.apache.commons.lang.StringUtils; -import org.bukkit.Location; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.bukkit.scheduler.BukkitRunnable; -import org.bukkit.scheduler.BukkitTask; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfigurationImplementation; import fr.skytasul.quests.api.AbstractHolograms; @@ -35,6 +22,19 @@ import fr.skytasul.quests.options.OptionStarterNPC; import fr.skytasul.quests.structure.pools.QuestPoolImplementation; import fr.skytasul.quests.utils.QuestUtils; +import org.apache.commons.lang.StringUtils; +import org.bukkit.Location; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.scheduler.BukkitRunnable; +import org.bukkit.scheduler.BukkitTask; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import java.util.*; +import java.util.Map.Entry; +import java.util.function.Predicate; public class BqNpcImplementation implements Located.LocatedEntity, BqNpc { @@ -80,7 +80,6 @@ public BqNpcImplementation(@NotNull WrappedInternalNpc wrappedNpc) { this.wrappedNpc = wrappedNpc; holograms = hologramText.enabled || hologramLaunch.enabled || hologramLaunchNo.enabled || hologramPool.enabled; - launcheableTask = startLauncheableTasks(); } public @NotNull WrappedInternalNpc getWrappedNpc() { @@ -117,8 +116,8 @@ public BqInternalNpc getNpc() { return placeholders; } - private BukkitTask startLauncheableTasks() { - return new BukkitRunnable() { + private void startLauncheableTasks() { + launcheableTask = new BukkitRunnable() { private int timer = 0; @Override @@ -208,8 +207,15 @@ public void run() { }.runTaskTimer(BeautyQuests.getInstance(), 20L, 20L); } - private BukkitTask startHologramsTask() { - return new BukkitRunnable() { + private void stopLauncheableTask() { + if (launcheableTask != null) { + launcheableTask.cancel(); + launcheableTask = null; + } + } + + private void startHologramsTask() { + hologramsTask = new BukkitRunnable() { @Override public void run() { LivingEntity en = null; // check if NPC is spawned and living @@ -343,18 +349,20 @@ private boolean isEmpty() { private void updatedObjects() { if (isEmpty()) { + stopLauncheableTask(); removeHolograms(true); - }else if (holograms && hologramsTask == null) { - hologramsTask = startHologramsTask(); + } else { + if (launcheableTask == null) + startLauncheableTasks(); + + if (holograms && hologramsTask == null) + startHologramsTask(); } } public void unload() { removeHolograms(true); - if (launcheableTask != null) { - launcheableTask.cancel(); - launcheableTask = null; - } + stopLauncheableTask(); } public void delete(String cause) { diff --git a/core/src/main/java/fr/skytasul/quests/npcs/BqNpcManagerImplementation.java b/core/src/main/java/fr/skytasul/quests/npcs/BqNpcManagerImplementation.java index 44fd5c4a..11239230 100644 --- a/core/src/main/java/fr/skytasul/quests/npcs/BqNpcManagerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/npcs/BqNpcManagerImplementation.java @@ -1,10 +1,12 @@ package fr.skytasul.quests.npcs; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.regex.Pattern; -import java.util.stream.Collectors; +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import fr.skytasul.quests.DefaultQuestFeatures; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.npcs.*; +import fr.skytasul.quests.api.npcs.BqInternalNpcFactory.BqInternalNpcFactoryCreatable; +import fr.skytasul.quests.utils.QuestUtils; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.entity.Entity; @@ -13,13 +15,11 @@ import org.bukkit.event.Cancellable; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import com.google.common.collect.BiMap; -import com.google.common.collect.HashBiMap; -import fr.skytasul.quests.DefaultQuestFeatures; -import fr.skytasul.quests.api.QuestsPlugin; -import fr.skytasul.quests.api.npcs.*; -import fr.skytasul.quests.api.npcs.BqInternalNpcFactory.BqInternalNpcFactoryCreatable; -import fr.skytasul.quests.utils.QuestUtils; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Pattern; +import java.util.stream.Collectors; public class BqNpcManagerImplementation implements BqNpcManager { @@ -63,7 +63,7 @@ public void addInternalFactory(@NotNull String key, @NotNull BqInternalNpcFactor if (!FACTORY_KEY_PATTERN.matcher(key).matches()) throw new IllegalArgumentException("Invalid factory key " + key); - QuestsPlugin.getPlugin().getLoggerExpanded().info("Adding " + key + " as a npc factory"); + QuestsPlugin.getPlugin().getLoggerExpanded().info("Adding " + key + " as an npc factory"); internalFactories.put(key, internalFactory); last = internalFactory; @@ -85,6 +85,8 @@ public void addInternalFactory(@NotNull String key, @NotNull BqInternalNpcFactor @Override public boolean isNPC(@NotNull Entity entity) { + if (!entity.getMetadata("NPC").isEmpty()) + return true; return internalFactories.values().stream().anyMatch(factory -> factory.isNPC(entity)); } diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionTimer.java b/core/src/main/java/fr/skytasul/quests/options/OptionTimer.java index 6de3bed3..1a9bc4d0 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionTimer.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionTimer.java @@ -1,7 +1,5 @@ package fr.skytasul.quests.options; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.inventory.ItemStack; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.parsers.DurationParser.MinecraftTimeUnit; import fr.skytasul.quests.api.gui.ItemUtils; @@ -11,42 +9,45 @@ import fr.skytasul.quests.api.quests.creation.QuestCreationGuiClickEvent; import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.api.utils.XMaterial; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.inventory.ItemStack; public class OptionTimer extends QuestOption { - + public OptionTimer() { super(OptionRepeatable.class); } - + @Override public Object save() { return getValue(); } - + @Override public void load(ConfigurationSection config, String key) { setValue(config.getInt(key)); } - + @Override public Integer cloneValue(Integer value) { return value; } - + @Override public boolean shouldDisplay(OptionSet options) { return options.getOption(OptionRepeatable.class).getValue(); } - + @Override public ItemStack getItemStack(OptionSet options) { return ItemUtils.item(XMaterial.CLOCK, Lang.timer.toString(), getLore()); } - + private String[] getLore() { - return new String[] { formatDescription(Lang.timerLore.toString()), "", formatValue(Utils.millisToHumanString(getValue() * 60 * 1000)) }; + return new String[] {formatDescription(Lang.timerLore.toString()), "", + formatValue(Utils.millisToHumanString(getValue() * 60L * 1000L))}; } - + @Override public void click(QuestCreationGuiClickEvent event) { Lang.TIMER.send(event.getPlayer()); @@ -59,5 +60,5 @@ public void click(QuestCreationGuiClickEvent event) { event.reopen(); }, MinecraftTimeUnit.MINUTE.getParser()).passNullIntoEndConsumer().start(); } - + } diff --git a/core/src/main/java/fr/skytasul/quests/players/AbstractPlayersManager.java b/core/src/main/java/fr/skytasul/quests/players/AbstractPlayersManager.java index f77f675c..77e341e9 100644 --- a/core/src/main/java/fr/skytasul/quests/players/AbstractPlayersManager.java +++ b/core/src/main/java/fr/skytasul/quests/players/AbstractPlayersManager.java @@ -43,6 +43,8 @@ public abstract class AbstractPlayersManager implements PlayersManager { public abstract @NotNull CompletableFuture removeQuestDatas(@NotNull Quest quest); + public abstract @NotNull CompletableFuture removePoolDatas(@NotNull QuestPool pool); + public abstract @NotNull PlayerQuestDatasImplementation createPlayerQuestDatas(@NotNull PlayerAccountImplementation acc, @NotNull Quest quest); diff --git a/core/src/main/java/fr/skytasul/quests/players/PlayerAccountImplementation.java b/core/src/main/java/fr/skytasul/quests/players/PlayerAccountImplementation.java index 6b0a1f56..635ce1ce 100644 --- a/core/src/main/java/fr/skytasul/quests/players/PlayerAccountImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/players/PlayerAccountImplementation.java @@ -1,13 +1,5 @@ package fr.skytasul.quests.players; -import java.util.*; -import java.util.concurrent.CompletableFuture; -import org.bukkit.OfflinePlayer; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.annotations.UnmodifiableView; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.data.SavableData; import fr.skytasul.quests.api.players.PlayerAccount; @@ -18,11 +10,19 @@ import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.players.accounts.AbstractAccount; +import org.bukkit.OfflinePlayer; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.UnmodifiableView; +import java.util.*; +import java.util.concurrent.CompletableFuture; public class PlayerAccountImplementation implements PlayerAccount { public static final List FORBIDDEN_DATA_ID = Arrays.asList("identifier", "quests", "pools"); - + public final AbstractAccount abstractAcc; protected final Map questDatas = new HashMap<>(); protected final Map poolDatas = new HashMap<>(); @@ -30,32 +30,32 @@ public class PlayerAccountImplementation implements PlayerAccount { protected final int index; private @Nullable PlaceholderRegistry placeholders; - + protected PlayerAccountImplementation(@NotNull AbstractAccount account, int index) { this.abstractAcc = account; this.index = index; } - + @Override public boolean isCurrent() { return abstractAcc.isCurrent(); } - + @Override public @NotNull OfflinePlayer getOfflinePlayer() { return abstractAcc.getOfflinePlayer(); } - + @Override public @Nullable Player getPlayer() { return abstractAcc.getPlayer(); } - + @Override public boolean hasQuestDatas(@NotNull Quest quest) { return questDatas.containsKey(quest.getId()); } - + @Override public @Nullable PlayerQuestDatasImplementation getQuestDatasIfPresent(@NotNull Quest quest) { return questDatas.get(quest.getId()); @@ -75,7 +75,7 @@ public boolean hasQuestDatas(@NotNull Quest quest) { public @NotNull CompletableFuture removeQuestDatas(@NotNull Quest quest) { return removeQuestDatas(quest.getId()); } - + @Override public @NotNull CompletableFuture removeQuestDatas(int id) { PlayerQuestDatasImplementation removed = questDatas.remove(id); @@ -84,21 +84,21 @@ public boolean hasQuestDatas(@NotNull Quest quest) { return BeautyQuests.getInstance().getPlayersManager().playerQuestDataRemoved(removed).thenApply(__ -> removed); } - + protected @Nullable PlayerQuestDatasImplementation removeQuestDatasSilently(int id) { return questDatas.remove(id); } - + @Override public @UnmodifiableView @NotNull Collection<@NotNull PlayerQuestDatas> getQuestsDatas() { return (Collection) questDatas.values(); } - + @Override public boolean hasPoolDatas(@NotNull QuestPool pool) { return poolDatas.containsKey(pool.getId()); } - + @Override public @NotNull PlayerPoolDatasImplementation getPoolDatas(@NotNull QuestPool pool) { PlayerPoolDatasImplementation datas = poolDatas.get(pool.getId()); @@ -108,12 +108,12 @@ public boolean hasPoolDatas(@NotNull QuestPool pool) { } return datas; } - + @Override public @NotNull CompletableFuture removePoolDatas(@NotNull QuestPool pool) { return removePoolDatas(pool.getId()); } - + @Override public @NotNull CompletableFuture removePoolDatas(int id) { PlayerPoolDatasImplementation removed = poolDatas.remove(id); @@ -122,12 +122,16 @@ public boolean hasPoolDatas(@NotNull QuestPool pool) { return BeautyQuests.getInstance().getPlayersManager().playerPoolDataRemoved(removed).thenApply(__ -> removed); } - + + protected @Nullable PlayerPoolDatasImplementation removePoolDatasSilently(int id) { + return poolDatas.remove(id); + } + @Override public @UnmodifiableView @NotNull Collection<@NotNull PlayerPoolDatas> getPoolDatas() { return (Collection) poolDatas.values(); } - + @Override public @Nullable T getData(@NotNull SavableData data) { if (!BeautyQuests.getInstance().getPlayersManager().getAccountDatas().contains(data)) @@ -141,12 +145,12 @@ public void setData(@NotNull SavableData data, @Nullable T value) { throw new IllegalArgumentException("The " + data.getId() + " account data has not been registered."); additionalDatas.put(data, value); } - + @Override public void resetDatas() { additionalDatas.clear(); } - + @Override public @NotNull PlaceholderRegistry getPlaceholdersRegistry() { if (placeholders == null) { @@ -169,29 +173,29 @@ public boolean equals(Object object) { return false; return abstractAcc.equals(((PlayerAccountImplementation) object).abstractAcc); } - + @Override public int hashCode() { int hash = 1; - + hash = hash * 31 + index; hash = hash * 31 + abstractAcc.hashCode(); - + return hash; } - + @Override public @NotNull String getName() { Player p = getPlayer(); return p == null ? debugName() : p.getName(); } - + @Override public @NotNull String getNameAndID() { Player p = getPlayer(); return p == null ? debugName() : p.getName() + " (# " + index + ")"; } - + @Override public @NotNull String debugName() { return abstractAcc.getIdentifier() + " (#" + index + ")"; @@ -205,5 +209,5 @@ public void serialize(@NotNull ConfigurationSection config) { config.set(entry.getKey().getId(), entry.getValue()); }); } - + } diff --git a/core/src/main/java/fr/skytasul/quests/players/PlayersManagerDB.java b/core/src/main/java/fr/skytasul/quests/players/PlayersManagerDB.java index b64f9287..e153bf90 100644 --- a/core/src/main/java/fr/skytasul/quests/players/PlayersManagerDB.java +++ b/core/src/main/java/fr/skytasul/quests/players/PlayersManagerDB.java @@ -1,16 +1,5 @@ package fr.skytasul.quests.players; -import java.sql.*; -import java.util.*; -import java.util.Map.Entry; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; -import java.util.stream.Collectors; -import org.apache.commons.lang.StringUtils; -import org.bukkit.entity.Player; -import org.bukkit.scheduler.BukkitRunnable; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.data.SQLDataSaver; @@ -23,6 +12,17 @@ import fr.skytasul.quests.utils.Database; import fr.skytasul.quests.utils.QuestUtils; import fr.skytasul.quests.utils.ThrowingConsumer; +import org.apache.commons.lang.StringUtils; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; +import java.sql.*; +import java.util.*; +import java.util.Map.Entry; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; +import java.util.stream.Collectors; public class PlayersManagerDB extends AbstractPlayersManager { @@ -47,6 +47,7 @@ public class PlayersManagerDB extends AbstractPlayersManager { private String getQuestsData; private String removeExistingQuestDatas; + private String removeExistingPoolDatas; private String updateFinished; private String updateTimer; @@ -249,6 +250,25 @@ public CompletableFuture removeQuestDatas(Quest quest) { }); } + @Override + public CompletableFuture removePoolDatas(QuestPool pool) { + return CompletableFuture.supplyAsync(() -> { + try (Connection connection = db.getConnection(); + PreparedStatement statement = connection.prepareStatement(removeExistingPoolDatas)) { + for (PlayerAccountImplementation acc : cachedAccounts.values()) { + acc.removePoolDatasSilently(pool.getId()); + } + statement.setInt(1, pool.getId()); + int amount = statement.executeUpdate(); + QuestsPlugin.getPlugin().getLoggerExpanded() + .debug("Removed " + amount + " in-database pool datas for pool " + pool.getId()); + return amount; + } catch (SQLException ex) { + throw new DataException("Failed to remove quest datas from database.", ex); + } + }); + } + public CompletableFuture hasAccounts(Player p) { return CompletableFuture.supplyAsync(() -> { try (Connection connection = db.getConnection(); @@ -279,6 +299,7 @@ public void load() { getQuestsData = "SELECT * FROM " + QUESTS_DATAS_TABLE + " WHERE account_id = ?"; removeExistingQuestDatas = "DELETE FROM " + QUESTS_DATAS_TABLE + " WHERE quest_id = ?"; + removeExistingPoolDatas = "DELETE FROM " + POOLS_DATAS_TABLE + " WHERE pool_id = ?"; updateFinished = prepareDatasStatement("finished"); updateTimer = prepareDatasStatement("timer"); diff --git a/core/src/main/java/fr/skytasul/quests/players/PlayersManagerYAML.java b/core/src/main/java/fr/skytasul/quests/players/PlayersManagerYAML.java index ad85b8ba..75007461 100644 --- a/core/src/main/java/fr/skytasul/quests/players/PlayersManagerYAML.java +++ b/core/src/main/java/fr/skytasul/quests/players/PlayersManagerYAML.java @@ -1,17 +1,5 @@ package fr.skytasul.quests.players; -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.util.*; -import java.util.Map.Entry; -import java.util.concurrent.*; -import org.apache.commons.lang.Validate; -import org.bukkit.Bukkit; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.entity.Player; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import fr.skytasul.quests.BeautyQuests; @@ -23,6 +11,17 @@ import fr.skytasul.quests.players.accounts.AbstractAccount; import fr.skytasul.quests.players.accounts.GhostAccount; import fr.skytasul.quests.utils.QuestUtils; +import org.apache.commons.lang.Validate; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Player; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.*; +import java.util.Map.Entry; +import java.util.concurrent.*; public class PlayersManagerYAML extends AbstractPlayersManager { @@ -138,6 +137,31 @@ public CompletableFuture removeQuestDatas(Quest quest) { }); } + @Override + public CompletableFuture removePoolDatas(QuestPool pool) { + return CompletableFuture.supplyAsync(() -> { + loadAllAccounts(); + int amount = 0; + + for (PlayerAccountImplementation account : loadedAccounts.values()) { + try { + if (account.removePoolDatas(pool).get() != null) { + // we can use the .get() method as the CompletableFuture created by the YAML players manager is + // already completed + amount++; + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new CompletionException(e); + } catch (ExecutionException e) { + throw new CompletionException(e); + } + } + + return amount; + }); + } + public boolean hasAccounts(Player p) { return identifiersIndex.containsValue(getIdentifier(p)); } @@ -168,68 +192,6 @@ void loadAllAccounts() { QuestsPlugin.getPlugin().getLoggerExpanded().info("Total loaded accounts: " + loadedAccounts.size()); } - public void debugDuplicate() { - for (Player p : Bukkit.getOnlinePlayers()) { - p.kickPlayer("§cCleanup operation."); - } - cachedAccounts.clear(); - - loadAllAccounts(); - int amount = 0; - - Map> playerAccounts = new HashMap<>(); - for (PlayerAccountImplementation acc : loadedAccounts.values()) { - List list = playerAccounts.get(acc.abstractAcc.getIdentifier()); - if (list == null) { - list = new ArrayList<>(); - playerAccounts.put(acc.abstractAcc.getIdentifier(), list); - } - list.add(acc); - } - QuestsPlugin.getPlugin().getLoggerExpanded().info(playerAccounts.size() + " unique identifiers."); - - List removed = new ArrayList<>(); - for (Entry> en : playerAccounts.entrySet()) { - if (removed.contains(en.getKey())) System.out.println("CRITICAL - Already removed " + en.getKey()); - - List list = en.getValue(); - - int maxID = 0; - int maxSize = 0; - for (int i = 0; i < list.size(); i++) { - PlayerAccountImplementation acc = list.get(i); - if (acc.questDatas.size() > maxSize) { - maxID = i; - maxSize = acc.questDatas.size(); - } - } - for (int i = 0; i < list.size(); i++) { - if (i != maxID) { - PlayerAccountImplementation acc = list.get(i); - int index = Utils.getKeyByValue(loadedAccounts, acc); - loadedAccounts.remove(index); - identifiersIndex.remove(index); - removePlayerFile(index); - amount++; - } - } - removed.add(en.getKey()); - } - - QuestsPlugin.getPlugin().getLoggerExpanded().info(amount + " duplicated accounts removeds. Total loaded accounts/identifiers: " + loadedAccounts.size() + "/" + identifiersIndex.size()); - QuestsPlugin.getPlugin().getLoggerExpanded().info("Now scanning for remaining duplicated accounts..."); - boolean dup = false; - for (String id : identifiersIndex.values()) { - int size = Utils.getKeysByValue(identifiersIndex, id).size(); - if (size != 1) { - dup = true; - System.out.println(size + " accounts with identifier " + id); - } - } - if (dup) QuestsPlugin.getPlugin().getLoggerExpanded().warning("There is still duplicated accounts."); - QuestsPlugin.getPlugin().getLoggerExpanded().info("Operation complete."); - } - private synchronized void addAccount(PlayerAccountImplementation acc) { Validate.notNull(acc); loadedAccounts.put(acc.index, acc); diff --git a/core/src/main/java/fr/skytasul/quests/rewards/TeleportationReward.java b/core/src/main/java/fr/skytasul/quests/rewards/TeleportationReward.java index d6663bf8..bfd1695b 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/TeleportationReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/TeleportationReward.java @@ -1,9 +1,5 @@ package fr.skytasul.quests.rewards; -import java.util.List; -import org.bukkit.Location; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; import fr.skytasul.quests.api.editors.WaitClick; import fr.skytasul.quests.api.gui.LoreBuilder; import fr.skytasul.quests.api.localization.Lang; @@ -12,6 +8,10 @@ import fr.skytasul.quests.gui.npc.NpcCreateGUI; import fr.skytasul.quests.utils.QuestUtils; import fr.skytasul.quests.utils.types.BQLocation; +import org.bukkit.Location; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; +import java.util.List; public class TeleportationReward extends AbstractReward { @@ -39,7 +39,7 @@ public AbstractReward clone() { protected void addLore(LoreBuilder loreBuilder) { super.addLore(loreBuilder); loreBuilder - .addDescriptionAsValue(Lang.Location.format(teleportation == null ? null : new BQLocation(teleportation))); + .addDescriptionAsValue(Lang.Location.format(teleportation == null ? null : BQLocation.of(teleportation))); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageInteractLocation.java b/core/src/main/java/fr/skytasul/quests/stages/StageInteractLocation.java index 926e8e04..a661c0d1 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageInteractLocation.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageInteractLocation.java @@ -1,16 +1,5 @@ package fr.skytasul.quests.stages; -import java.util.Objects; -import org.bukkit.Location; -import org.bukkit.block.Block; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.block.Action; -import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.inventory.EquipmentSlot; -import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.editors.WaitBlockClick; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; @@ -27,6 +16,17 @@ import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.utils.types.BQLocation; +import org.bukkit.Location; +import org.bukkit.block.Block; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.EquipmentSlot; +import org.jetbrains.annotations.NotNull; +import java.util.Objects; @LocatableType (types = { LocatedType.BLOCK, LocatedType.OTHER }) public class StageInteractLocation extends AbstractStage implements Locatable.PreciseLocatable, Listener { @@ -109,7 +109,7 @@ public static StageInteractLocation deserialize(ConfigurationSection section, St public static class Creator extends StageCreation { private boolean leftClick = false; - private Location location; + private BQLocation location; public Creator(@NotNull StageCreationContext context) { super(context); @@ -137,8 +137,8 @@ public void setLeftClick(boolean leftClick) { } public void setLocation(@NotNull Location location) { - this.location = Objects.requireNonNull(location); - getLine().refreshItemLoreOptionValue(7, Lang.Location.format(getBQLocation())); + this.location = BQLocation.of(Objects.requireNonNull(location)); + getLine().refreshItemLoreOptionValue(7, Lang.Location.format(this.location)); } @Override @@ -151,10 +151,6 @@ public void start(Player p) { }, ItemUtils.item(XMaterial.STICK, Lang.blockLocation.toString())).start(); } - private @NotNull BQLocation getBQLocation() { - return new BQLocation(location); - } - @Override public void edit(StageInteractLocation stage) { super.edit(stage); @@ -164,7 +160,7 @@ public void edit(StageInteractLocation stage) { @Override public StageInteractLocation finishStage(StageController controller) { - return new StageInteractLocation(controller, leftClick, getBQLocation()); + return new StageInteractLocation(controller, leftClick, location); } } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageLocation.java b/core/src/main/java/fr/skytasul/quests/stages/StageLocation.java index 7f8220fc..0de9b282 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageLocation.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageLocation.java @@ -1,13 +1,5 @@ package fr.skytasul.quests.stages; -import java.util.regex.Pattern; -import org.bukkit.Location; -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.PlayerMoveEvent; -import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.WaitClick; import fr.skytasul.quests.api.editors.parsers.NumberParser; @@ -28,6 +20,14 @@ import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.gui.npc.NpcCreateGUI; import fr.skytasul.quests.utils.types.BQLocation; +import org.bukkit.Location; +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.PlayerMoveEvent; +import org.jetbrains.annotations.NotNull; +import java.util.regex.Pattern; @LocatableType (types = LocatedType.OTHER) public class StageLocation extends AbstractStage implements Locatable.PreciseLocatable, Listener { @@ -123,7 +123,7 @@ public void setupLine(@NotNull StageGuiLine line) { line.setItem(SLOT_LOCATION, ItemUtils.item(XMaterial.STICK, Lang.stageLocationLocation.toString()), event -> { Lang.LOCATION_GO.send(event.getPlayer()); new WaitClick(event.getPlayer(), event::reopen, NpcCreateGUI.validMove, () -> { - setLocation(new BQLocation(event.getPlayer().getLocation())); + setLocation(BQLocation.of(event.getPlayer().getLocation())); event.reopen(); }).start(); }); @@ -157,7 +157,7 @@ public void setPattern(Pattern pattern) { } private BQLocation getBQLocation() { - BQLocation loc = new BQLocation(location); + BQLocation loc = BQLocation.of(location); if (pattern != null) loc.setWorldPattern(pattern); return loc; } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageNPC.java b/core/src/main/java/fr/skytasul/quests/stages/StageNPC.java index 34cf9608..215ed6c4 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageNPC.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageNPC.java @@ -1,19 +1,5 @@ package fr.skytasul.quests.stages; -import java.util.ArrayList; -import java.util.List; -import org.bukkit.Location; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.inventory.ItemStack; -import org.bukkit.scheduler.BukkitRunnable; -import org.bukkit.scheduler.BukkitTask; -import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfigurationImplementation; import fr.skytasul.quests.api.AbstractHolograms; @@ -43,6 +29,20 @@ import fr.skytasul.quests.npcs.BQNPCClickEvent; import fr.skytasul.quests.utils.QuestUtils; import fr.skytasul.quests.utils.types.DialogRunnerImplementation; +import org.bukkit.Location; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.inventory.ItemStack; +import org.bukkit.scheduler.BukkitRunnable; +import org.bukkit.scheduler.BukkitTask; +import org.jetbrains.annotations.NotNull; +import java.util.ArrayList; +import java.util.List; @LocatableType(types = LocatedType.ENTITY) public class StageNPC extends AbstractStage implements Locatable.PreciseLocatable, Dialogable, Listener { @@ -210,7 +210,8 @@ public void onClick(BQNPCClickEvent e) { e.setCancelled(dialogRunner.onClick(p).shouldCancel()); } - protected String getNpcName() { + @Override + public String getNpcName() { if (npc == null) return "§c§lunknown NPC " + npcID; if (dialog != null && dialog.getNpcName() != null) diff --git a/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPoolImplementation.java b/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPoolImplementation.java index b009f6ef..0e6fd593 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPoolImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPoolImplementation.java @@ -1,17 +1,5 @@ package fr.skytasul.quests.structure.pools; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ThreadLocalRandom; -import java.util.stream.Collectors; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.gui.ItemUtils; @@ -30,6 +18,18 @@ import fr.skytasul.quests.npcs.BqNpcImplementation; import fr.skytasul.quests.players.PlayerPoolDatasImplementation; import fr.skytasul.quests.utils.QuestUtils; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ThreadLocalRandom; +import java.util.stream.Collectors; public class QuestPoolImplementation implements Comparable, QuestPool { @@ -173,8 +173,8 @@ public ItemStack getItemStack(String action) { } @Override - public CompletableFuture resetPlayer(PlayerAccount acc) { - return acc.removePoolDatas(this); + public CompletableFuture resetPlayer(PlayerAccount acc) { + return acc.removePoolDatas(this).thenApply(__ -> true); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/utils/QuestUtils.java b/core/src/main/java/fr/skytasul/quests/utils/QuestUtils.java index 49711292..908b53bd 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/QuestUtils.java +++ b/core/src/main/java/fr/skytasul/quests/utils/QuestUtils.java @@ -153,11 +153,12 @@ public static void spawnFirework(Location lc, FireworkMeta meta) { fw.setMetadata("questFinish", new FixedMetadataValue(BeautyQuests.getInstance(), true)); fw.setFireworkMeta(meta); }; - if ((MinecraftVersion.MAJOR >= 12 && MinecraftVersion.MAJOR < 17) || MinecraftVersion.MAJOR >= 20) { + if (MinecraftVersion.isHigherThan(20, 6)) { lc.getWorld().spawn(lc, Firework.class, fw -> fwConsumer.accept(fw)); - // Much better to use the built-in since 1.12 method to do operations on entity + // Much better to use the built-in method to do operations on entity // before it is sent to the players, as it will not create flickering. - // From 1.17.1 to 1.19.4, the method was moved from World to RegionAccessor. + // There was some weird shit done between 1.17 and 1.20 with this method + // so we will keep it like that } else { fwConsumer.accept(lc.getWorld().spawn(lc, Firework.class)); } diff --git a/core/src/main/java/fr/skytasul/quests/utils/nms/NMS.java b/core/src/main/java/fr/skytasul/quests/utils/nms/NMS.java index 79de5af2..1b9891ca 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/nms/NMS.java +++ b/core/src/main/java/fr/skytasul/quests/utils/nms/NMS.java @@ -77,11 +77,16 @@ public static boolean isValid() { String versionNms; if (!BeautyQuests.getInstance().isRunningPaper() || !MinecraftVersion.isHigherThan(20, 5)) { - versionNms = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3].substring(1); + versionNms = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3]; } else { - versionNms = "1_20_R4"; - // TODO: find better way + try { + Class paperMapping = Class.forName("io.papermc.paper.util.MappingEnvironment"); + versionNms = (String) paperMapping.getDeclaredField("LEGACY_CB_VERSION").get(null); + } catch (ReflectiveOperationException ex) { + throw new RuntimeException("Impossible to get server internals version", ex); + } } + versionNms = versionNms.substring(1); try { nms = (NMS) Class.forName("fr.skytasul.quests.utils.nms.v" + versionNms).newInstance(); diff --git a/core/src/main/java/fr/skytasul/quests/utils/types/BQLocation.java b/core/src/main/java/fr/skytasul/quests/utils/types/BQLocation.java index dc5741dd..0ca02aef 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/types/BQLocation.java +++ b/core/src/main/java/fr/skytasul/quests/utils/types/BQLocation.java @@ -1,9 +1,9 @@ package fr.skytasul.quests.utils.types; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import java.util.regex.Pattern; +import fr.skytasul.quests.api.stages.types.Locatable; +import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; +import fr.skytasul.quests.api.utils.messaging.HasPlaceholders; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import org.apache.commons.lang.Validate; import org.bukkit.Bukkit; import org.bukkit.Location; @@ -12,10 +12,10 @@ import org.bukkit.util.NumberConversions; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import fr.skytasul.quests.api.stages.types.Locatable; -import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; -import fr.skytasul.quests.api.utils.messaging.HasPlaceholders; -import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.regex.Pattern; public class BQLocation extends Location implements Locatable.Located, HasPlaceholders { @@ -23,10 +23,6 @@ public class BQLocation extends Location implements Locatable.Located, HasPlaceh private @Nullable PlaceholderRegistry placeholders; - public BQLocation(@NotNull Location bukkit) { - this(bukkit.getWorld(), bukkit.getX(), bukkit.getY(), bukkit.getZ(), bukkit.getYaw(), bukkit.getPitch()); - } - public BQLocation(World world, double x, double y, double z) { this(world, x, y, z, 0, 0); } @@ -193,4 +189,15 @@ public static BQLocation deserialize(@NotNull Map args) { return new BQLocation(world, x, y, z, yaw, pitch); } + public static BQLocation of(Location location) { + if (location instanceof BQLocation) { + BQLocation bqLoc = (BQLocation) location; + return new BQLocation(bqLoc.getWorldName(), bqLoc.getX(), bqLoc.getY(), bqLoc.getZ(), bqLoc.getYaw(), + bqLoc.getPitch()); + } else { + return new BQLocation(location.getWorld(), location.getX(), location.getY(), location.getZ(), location.getYaw(), + location.getPitch()); + } + } + } diff --git a/core/src/main/resources/config.yml b/core/src/main/resources/config.yml index 17f3466a..1ec928be 100644 --- a/core/src/main/resources/config.yml +++ b/core/src/main/resources/config.yml @@ -109,8 +109,26 @@ questsSelection: # - Quests Menu - # Options related to the "/quests" menu questsMenu: - # Enabled tabs in the quests menu. Valid parameters: NOT_STARTED, IN_PROGRESS, FINISHED - enabledTabs: [NOT_STARTED, IN_PROGRESS, FINISHED] + # Configuration of the tabs in the menu + tabs: + # This tab shows the quests the player has previously completed. + finished: + # Whether the tab will appear in the menu + enabled: true + # The icon in the bar at the right + icon: BOOK + # The color of the vertical separator (if enabled) + color: GREEN + # This tab shows the quests currently being done by the player. + in progress: + enabled: true + icon: WRITABLE_BOOK + color: YELLOW + # This tab shows the quests the player can start. + not started: + enabled: true + icon: PAPER + color: RED # Will the "/quests" menu open automatically on the "not started" tab instead of the "quests in progress" one if it is empty openNotStartedTabWhenEmpty: true # Allows player to cancel quests they have started with the GUI diff --git a/core/src/main/resources/locales/en_US.yml b/core/src/main/resources/locales/en_US.yml index 71a1d97b..b8642c6b 100644 --- a/core/src/main/resources/locales/en_US.yml +++ b/core/src/main/resources/locales/en_US.yml @@ -146,6 +146,7 @@ msg: resetPlayerPool: timer: §aYou have reset the {pool} pool timer of {player}. full: §aYou have reset the {pool} pool datas of {player}. + resetPool: Removed datas of the pool for {player_amount} players. startPlayerPool: error: 'Failed to start the pool {pool} for {player}.' success: 'Started pool {pool} to {player}. Result: {result}' diff --git a/core/src/main/resources/locales/vi_VN.yml b/core/src/main/resources/locales/vi_VN.yml index 0b53ede0..362172c3 100644 --- a/core/src/main/resources/locales/vi_VN.yml +++ b/core/src/main/resources/locales/vi_VN.yml @@ -750,7 +750,7 @@ scoreboard: fish: '§eCâu §6{items}' interact: '§eNhấn vào khối tại §6{x}' interactMaterial: '§eNhấn vào khối §6{block}' - items: '§eMang cho §6{dialog_npc_name}§e:' + items: '§eMang cho §6{dialog_npc_name}§e: {items}' location: '§eĐi đên §6{target_x}§e, §6{target_y}§e, §6{target_z}§e in §6{target_world}' melt: '§eNung §6{items}' mine: '§eĐào {blocks}' diff --git a/core/src/main/resources/plugin.yml b/core/src/main/resources/plugin.yml index c09e2e60..6d769ca3 100644 --- a/core/src/main/resources/plugin.yml +++ b/core/src/main/resources/plugin.yml @@ -11,7 +11,7 @@ softdepend: - MythicMobs - Vault - PlaceholderAPI -- SkillAPI +- Fabled - HolographicDisplays - Jobs - Factions @@ -27,8 +27,8 @@ softdepend: - UltimateTimber - ServersNPC - Citizens +- FancyNpcs - ZNPCsPlus -- ProSkillAPI - BlueMap - Sentinel - AdvancedSpawners @@ -37,6 +37,7 @@ softdepend: - LevelledMobs - WildStacker - ItemsAdder +- StackMob #commands: # beautyquests: diff --git a/dist/pom.xml b/dist/pom.xml index eab0eaaa..e3279d6e 100644 --- a/dist/pom.xml +++ b/dist/pom.xml @@ -177,5 +177,12 @@ jar compile + + ${project.groupId} + beautyquests-v1_21_R1 + ${revision} + jar + compile + \ No newline at end of file diff --git a/integrations/libs.sh b/integrations/libs.sh index fb8e01ef..ea4bf95c 100755 --- a/integrations/libs.sh +++ b/integrations/libs.sh @@ -19,7 +19,6 @@ echo -e "Maven path: $mavenPath\e[39m" "$mavenPath" install:install-file -Dfile=$jarsPath/Jobs.jar -DgroupId=com.gamingmesh -DartifactId=jobs -Dversion=5.1.0.1 -Dpackaging=jar -DgeneratePom=true "$mavenPath" install:install-file -Dfile=$jarsPath/McCombatLevel.jar -DgroupId=com.gmail.mrphpfan -DartifactId=mccombatlevel -Dversion=1.0 -Dpackaging=jar -DgeneratePom=true "$mavenPath" install:install-file -Dfile=$jarsPath/mcMMO.jar -DgroupId=com.gmail.nossr50 -DartifactId=mcmmo -Dversion=1.0 -Dpackaging=jar -DgeneratePom=true -"$mavenPath" install:install-file -Dfile=$jarsPath/SkillAPI.jar -DgroupId=com.suxy -DartifactId=skillapi -Dversion=1.0 -Dpackaging=jar -DgeneratePom=true "$mavenPath" install:install-file -Dfile=$jarsPath/Boss.jar -DgroupId=org.mineacademy -DartifactId=boss -Dversion=4.2.1 -Dpackaging=jar -DgeneratePom=true "$mavenPath" install:install-file -Dfile=$jarsPath/CMI.jar -DgroupId=com.zrips -DartifactId=cmi -Dversion=9.0.2.1 -Dpackaging=jar -DgeneratePom=true "$mavenPath" install:install-file -Dfile=$jarsPath/CMILib.jar -DgroupId=com.zrips -DartifactId=cmilib -Dversion=1.2.3.3 -Dpackaging=jar -DgeneratePom=true diff --git a/integrations/pom.xml b/integrations/pom.xml index 5de75407..50163c68 100644 --- a/integrations/pom.xml +++ b/integrations/pom.xml @@ -14,7 +14,8 @@ placeholderapi - https://repo.extendedclip.com/content/repositories/placeholderapi/ + + https://repo.extendedclip.com/content/repositories/placeholderapi/ dynmap @@ -32,6 +33,10 @@ mineacademy-repo https://bitbucket.org/kangarko/libraries/raw/master + + fancyplugins-repo + https://repo.fancyplugins.de/releases + jitpack.io https://jitpack.io @@ -73,11 +78,15 @@ pyr-snapshots https://repo.pyr.lol/snapshots + + sonatype + https://s01.oss.sonatype.org/content/repositories/snapshots + - fr.skytasul + fr.skytasul beautyquests-api ${revision} provided @@ -110,6 +119,12 @@ 2.7.3-SNAPSHOT provided + + de.oliver + FancyNpcs + 2.2.1 + provided + io.github.gonalez znpcs @@ -177,9 +192,9 @@ provided - com.github.promcteam - proskillapi - 1.1.7.0.3 + studio.magemonkey + fabled + 1.0.0-R0.33-SNAPSHOT provided @@ -200,12 +215,12 @@ 2.8.5 provided - - com.github.lokka30 - LevelledMobs - 3.2.6 + com.bgsoftware WildStackerAPI @@ -230,6 +245,12 @@ 1.5.2-SNAPSHOT provided + + uk.antiperson.stackmob + StackMob + 5.8.2 + provided + @@ -280,12 +301,6 @@ 1.0 provided - - com.suxy - skillapi - 1.0 - provided - com.zrips cmi diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/IntegrationsLoader.java b/integrations/src/main/java/fr/skytasul/quests/integrations/IntegrationsLoader.java index f996b4fb..9e9c1644 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/IntegrationsLoader.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/IntegrationsLoader.java @@ -10,6 +10,9 @@ import fr.skytasul.quests.api.utils.IntegrationManager; import fr.skytasul.quests.api.utils.IntegrationManager.BQDependency; import fr.skytasul.quests.api.utils.XMaterial; +import fr.skytasul.quests.integrations.fabled.FabledClassRequirement; +import fr.skytasul.quests.integrations.fabled.FabledLevelRequirement; +import fr.skytasul.quests.integrations.fabled.FabledXpReward; import fr.skytasul.quests.integrations.factions.FactionRequirement; import fr.skytasul.quests.integrations.jobs.JobLevelRequirement; import fr.skytasul.quests.integrations.maps.BQBlueMap; @@ -21,9 +24,6 @@ import fr.skytasul.quests.integrations.placeholders.PapiMessageProcessor; import fr.skytasul.quests.integrations.placeholders.PlaceholderRequirement; import fr.skytasul.quests.integrations.placeholders.QuestsPlaceholders; -import fr.skytasul.quests.integrations.skillapi.ClassRequirement; -import fr.skytasul.quests.integrations.skillapi.SkillAPILevelRequirement; -import fr.skytasul.quests.integrations.skillapi.SkillAPIXpReward; import fr.skytasul.quests.integrations.vault.economy.MoneyRequirement; import fr.skytasul.quests.integrations.vault.economy.MoneyReward; import fr.skytasul.quests.integrations.vault.permission.PermissionReward; @@ -55,6 +55,10 @@ public IntegrationsLoader() { manager.addDependency(new BQDependency("ZNPCsPlus", this::registerZnpcsPlus)); + manager.addDependency(new BQDependency("FancyNpcs", () -> { + QuestsAPI.getAPI().addNpcFactory("fancynpcs", new BQFancyNPCs()); + })); + manager.addDependency(new BQDependency("Citizens", () -> { QuestsAPI.getAPI().addNpcFactory("citizens", new BQCitizens()); QuestsAPI.getAPI().registerMobFactory(new CitizensFactory()); @@ -75,9 +79,13 @@ public IntegrationsLoader() { manager.addDependency(new BQDependency("WildStacker", BQWildStacker::initialize)); + manager.addDependency(new BQDependency("StackMob", BQStackMob::initialize)); + // REWARDS / REQUIREMENTS - manager.addDependency(new BQDependency("SkillAPI", this::registerSkillApi).addPluginName("ProSkillAPI")); + manager.addDependency(new BQDependency("Fabled", this::registerFabled, null, this::isFabledValid) + .addPluginName("ProSkillAPI").addPluginName("SkillAPI") // for warning message + ); manager.addDependency(new BQDependency("Jobs", this::registerJobs)); manager.addDependency(new BQDependency("Factions", this::registerFactions)); manager.addDependency(new BQDependency("mcMMO", this::registerMcMmo)); @@ -174,15 +182,24 @@ private void registerJobs() { JobLevelRequirement::new)); } - private void registerSkillApi() { - QuestsAPI.getAPI().getRequirements().register(new RequirementCreator("classRequired", ClassRequirement.class, - ItemUtils.item(XMaterial.GHAST_TEAR, Lang.RClass.toString()), ClassRequirement::new)); + private void registerFabled() { + QuestsAPI.getAPI().getRequirements().register(new RequirementCreator("classRequired", FabledClassRequirement.class, + ItemUtils.item(XMaterial.GHAST_TEAR, Lang.RClass.toString()), FabledClassRequirement::new)); QuestsAPI.getAPI().getRequirements() - .register(new RequirementCreator("skillAPILevelRequired", SkillAPILevelRequirement.class, + .register(new RequirementCreator("skillAPILevelRequired", FabledLevelRequirement.class, ItemUtils.item(XMaterial.EXPERIENCE_BOTTLE, Lang.RSkillAPILevel.toString()), - SkillAPILevelRequirement::new)); - QuestsAPI.getAPI().getRewards().register(new RewardCreator("skillAPI-exp", SkillAPIXpReward.class, - ItemUtils.item(XMaterial.EXPERIENCE_BOTTLE, Lang.RWSkillApiXp.toString()), SkillAPIXpReward::new)); + FabledLevelRequirement::new)); + QuestsAPI.getAPI().getRewards().register(new RewardCreator("skillAPI-exp", FabledXpReward.class, + ItemUtils.item(XMaterial.EXPERIENCE_BOTTLE, Lang.RWSkillApiXp.toString()), FabledXpReward::new)); + } + + private boolean isFabledValid(Plugin plugin) { + if (plugin.getName().equals("SkillAPI") || plugin.getName().equals("ProSkillAPI")) { + QuestsPlugin.getPlugin().getLogger().warning( + "SkillAPI and ProSKillAPI are no longer supported. You must upgrade to their newer version: Fabled (https://www.spigotmc.org/resources/91913)"); + return false; + } + return true; } private boolean isUltimateTimberValid(Plugin plugin) { @@ -212,6 +229,7 @@ private void registerMythicMobs() { try { Class.forName("io.lumine.mythic.api.MythicPlugin"); QuestsAPI.getAPI().registerMobFactory(new MythicMobs5()); + QuestsAPI.getAPI().addNpcFactory("mythicmobs", new BQMythicMobs5Npcs()); } catch (ClassNotFoundException ex) { QuestsAPI.getAPI().registerMobFactory(new MythicMobs()); } diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/skillapi/ClassRequirement.java b/integrations/src/main/java/fr/skytasul/quests/integrations/fabled/FabledClassRequirement.java similarity index 58% rename from integrations/src/main/java/fr/skytasul/quests/integrations/skillapi/ClassRequirement.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/fabled/FabledClassRequirement.java index 9c7c5b63..4eeb9e6b 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/skillapi/ClassRequirement.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/fabled/FabledClassRequirement.java @@ -1,16 +1,5 @@ -package fr.skytasul.quests.integrations.skillapi; +package fr.skytasul.quests.integrations.fabled; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Function; -import java.util.stream.Collectors; -import org.bukkit.DyeColor; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; -import org.bukkit.inventory.ItemStack; -import com.sucy.skill.api.classes.RPGClass; -import com.sucy.skill.api.player.PlayerClass; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.LoreBuilder; @@ -19,44 +8,57 @@ import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.requirements.AbstractRequirement; +import org.bukkit.DyeColor; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; +import studio.magemonkey.fabled.Fabled; +import studio.magemonkey.fabled.api.classes.FabledClass; +import studio.magemonkey.fabled.api.player.PlayerClass; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; + +public class FabledClassRequirement extends AbstractRequirement { -public class ClassRequirement extends AbstractRequirement { + public List classes; - public List classes; - - public ClassRequirement() { + public FabledClassRequirement() { this(null, null, new ArrayList<>()); } - - public ClassRequirement(String customDescription, String customReason, List classes) { + + public FabledClassRequirement(String customDescription, String customReason, List classes) { super(customDescription, customReason); this.classes = classes; } public List getClassesName(){ List ls = new ArrayList<>(); - for (RPGClass cl : classes) ls.add(cl.getName()); + for (FabledClass cl : classes) + ls.add(cl.getName()); return ls; } - + public void addClass(Object classe){ - classes.add((RPGClass) classe); + classes.add((FabledClass) classe); } - + @Override public boolean test(Player p) { if (classes.isEmpty()) return true; - for (RPGClass classe : classes){ - PlayerClass mainClass = com.sucy.skill.SkillAPI.getPlayerData(p).getMainClass(); + for (FabledClass classe : classes) { + PlayerClass mainClass = Fabled.getData(p).getMainClass(); if (mainClass != null && mainClass.getData() == classe) return true; } return false; } - + @Override public String getDefaultDescription(Player p) { return Lang.RDClass.quickFormat("classes", String.join(" " + Lang.Or.toString() + " ", - (Iterable) () -> classes.stream().map(RPGClass::getName).iterator())); + (Iterable) () -> classes.stream().map(FabledClass::getName).iterator())); } @Override @@ -64,59 +66,60 @@ protected void addLore(LoreBuilder loreBuilder) { super.addLore(loreBuilder); loreBuilder.addDescription(classes.size() + " classes"); } - + @Override public void itemClick(QuestObjectClickEvent event) { - new ListGUI(Lang.INVENTORY_CLASSES_REQUIRED.toString(), DyeColor.GREEN, classes) { - + new ListGUI(Lang.INVENTORY_CLASSES_REQUIRED.toString(), DyeColor.GREEN, classes) { + @Override - public ItemStack getObjectItemStack(RPGClass object) { + public ItemStack getObjectItemStack(FabledClass object) { return ItemUtils.loreAdd(object.getIcon(), createLoreBuilder(object).toLoreArray()); } - + @Override - public void createObject(Function callback) { - new PagedGUI(Lang.INVENTORY_CLASSES_LIST.toString(), DyeColor.PURPLE, SkillAPI.getClasses()) { - + public void createObject(Function callback) { + new PagedGUI(Lang.INVENTORY_CLASSES_LIST.toString(), DyeColor.PURPLE, + Fabled.getClasses().values()) { + @Override - public ItemStack getItemStack(RPGClass object) { + public ItemStack getItemStack(FabledClass object) { return object.getIcon(); } - + @Override - public void click(RPGClass existing, ItemStack item, ClickType clickType) { + public void click(FabledClass existing, ItemStack item, ClickType clickType) { callback.apply(existing); } }.open(player); } - + @Override - public void finish(List objects) { + public void finish(List objects) { classes = objects; event.reopenGUI(); } - + }.open(event.getPlayer()); } - + @Override public AbstractRequirement clone() { - return new ClassRequirement(getCustomDescription(), getCustomReason(), new ArrayList<>(classes)); + return new FabledClassRequirement(getCustomDescription(), getCustomReason(), new ArrayList<>(classes)); } - + @Override public void save(ConfigurationSection section) { super.save(section); if (!classes.isEmpty()) - section.set("classes", classes.stream().map(RPGClass::getName).collect(Collectors.toList())); + section.set("classes", classes.stream().map(FabledClass::getName).collect(Collectors.toList())); } - + @Override public void load(ConfigurationSection section) { super.load(section); if (!section.contains("classes")) return; for (String s : section.getStringList("classes")) { - RPGClass classe = com.sucy.skill.SkillAPI.getClasses().get(s.toLowerCase()); + FabledClass classe = Fabled.getClasses().get(s.toLowerCase()); if (classe == null) { QuestsPlugin.getPlugin().getLoggerExpanded().warning("Class with name " + s + " no longer exists."); continue; @@ -124,5 +127,5 @@ public void load(ConfigurationSection section) { classes.add(classe); } } - + } diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/skillapi/SkillAPILevelRequirement.java b/integrations/src/main/java/fr/skytasul/quests/integrations/fabled/FabledLevelRequirement.java similarity index 69% rename from integrations/src/main/java/fr/skytasul/quests/integrations/skillapi/SkillAPILevelRequirement.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/fabled/FabledLevelRequirement.java index bc1b3aee..dcece324 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/skillapi/SkillAPILevelRequirement.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/fabled/FabledLevelRequirement.java @@ -1,27 +1,28 @@ -package fr.skytasul.quests.integrations.skillapi; +package fr.skytasul.quests.integrations.fabled; -import org.bukkit.entity.Player; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.api.requirements.TargetNumberRequirement; import fr.skytasul.quests.api.utils.ComparisonMethod; +import org.bukkit.entity.Player; +import studio.magemonkey.fabled.Fabled; -public class SkillAPILevelRequirement extends TargetNumberRequirement { - - public SkillAPILevelRequirement() { +public class FabledLevelRequirement extends TargetNumberRequirement { + + public FabledLevelRequirement() { this(null, null, 0, ComparisonMethod.GREATER_OR_EQUAL); } - - public SkillAPILevelRequirement(String customDescription, String customReason, double target, + + public FabledLevelRequirement(String customDescription, String customReason, double target, ComparisonMethod comparison) { super(customDescription, customReason, target, comparison); } @Override public double getPlayerTarget(Player p) { - return SkillAPI.getLevel(p); + return Fabled.getData(p).getMainClass().getLevel(); } - + @Override protected String getPlaceholderName() { return "level"; @@ -31,17 +32,17 @@ protected String getPlaceholderName() { protected String getDefaultReason(Player player) { return Lang.REQUIREMENT_LEVEL.format(this); } - + @Override public Class numberClass() { return Integer.class; } - + @Override public void sendHelpString(Player p) { Lang.CHOOSE_XP_REQUIRED.send(p); } - + @Override public String getDefaultDescription(Player p) { return Lang.RDLevel.format(this); @@ -49,7 +50,7 @@ public String getDefaultDescription(Player p) { @Override public AbstractRequirement clone() { - return new SkillAPILevelRequirement(getCustomDescription(), getCustomReason(), target, comparison); + return new FabledLevelRequirement(getCustomDescription(), getCustomReason(), target, comparison); } } diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/skillapi/SkillAPIXpReward.java b/integrations/src/main/java/fr/skytasul/quests/integrations/fabled/FabledXpReward.java similarity index 83% rename from integrations/src/main/java/fr/skytasul/quests/integrations/skillapi/SkillAPIXpReward.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/fabled/FabledXpReward.java index d23a96cc..008c0475 100755 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/skillapi/SkillAPIXpReward.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/fabled/FabledXpReward.java @@ -1,10 +1,5 @@ -package fr.skytasul.quests.integrations.skillapi; +package fr.skytasul.quests.integrations.fabled; -import java.util.Arrays; -import java.util.List; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.parsers.NumberParser; import fr.skytasul.quests.api.gui.LoreBuilder; @@ -12,27 +7,34 @@ import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import studio.magemonkey.fabled.Fabled; +import studio.magemonkey.fabled.api.enums.ExpSource; +import java.util.Arrays; +import java.util.List; -public class SkillAPIXpReward extends AbstractReward { +public class FabledXpReward extends AbstractReward { public int exp = 0; - public SkillAPIXpReward() {} + public FabledXpReward() {} - public SkillAPIXpReward(String customDescription, int exp) { + public FabledXpReward(String customDescription, int exp) { super(customDescription); this.exp = exp; } @Override public List give(Player p) { - SkillAPI.giveExp(p, exp); + Fabled.getData(p).giveExp(exp, ExpSource.QUEST); return Arrays.asList(getXpAmountString()); } @Override public AbstractReward clone() { - return new SkillAPIXpReward(getCustomDescription(), exp); + return new FabledXpReward(getCustomDescription(), exp); } @Override diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/maps/BQBlueMap.java b/integrations/src/main/java/fr/skytasul/quests/integrations/maps/BQBlueMap.java index d4cccc45..a213fdf8 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/maps/BQBlueMap.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/maps/BQBlueMap.java @@ -1,7 +1,5 @@ package fr.skytasul.quests.integrations.maps; -import java.util.function.Consumer; -import org.bukkit.Location; import de.bluecolored.bluemap.api.BlueMapAPI; import de.bluecolored.bluemap.api.BlueMapMap; import de.bluecolored.bluemap.api.BlueMapWorld; @@ -12,14 +10,15 @@ import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.integrations.IntegrationsConfiguration; +import org.bukkit.Location; +import java.util.function.Consumer; public class BQBlueMap extends AbstractMapIntegration { - + private static final String MARKERSET_ID = "beautyquests.markerset"; private Consumer enableConsumer; - private MarkerSet set; - + @Override public boolean isEnabled() { return IntegrationsConfiguration.getConfiguration().dynmapMarkerIcon() != null @@ -30,13 +29,7 @@ public boolean isEnabled() { protected void initializeMarkers(Runnable initializeQuests) { BlueMapAPI.onEnable(enableConsumer = api -> { try { - set = MarkerSet.builder() - .label(IntegrationsConfiguration.getConfiguration().dynmapSetName()) - .defaultHidden(false) - .toggleable(true) - .build(); QuestsPlugin.getPlugin().getLoggerExpanded().debug("Enabled BlueMap integration."); - initializeQuests.run(); }catch (Exception e) { QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error occurred while loading BlueMap integration.", e); @@ -44,7 +37,7 @@ protected void initializeMarkers(Runnable initializeQuests) { } }); } - + @Override public void unload() { BlueMapAPI.unregisterListener(enableConsumer); @@ -52,34 +45,43 @@ public void unload() { api.getMaps().forEach(map -> map.getMarkerSets().remove(MARKERSET_ID)); }); } - + @Override protected void addMarker(Quest quest, Location lc) { BlueMapAPI.getInstance().ifPresent(api -> { api.getWorld(lc.getWorld()).map(BlueMapWorld::getMaps).ifPresent(maps -> { - int i = 0; for (BlueMapMap map : maps) { - POIMarker marker = POIMarker.toBuilder() + MarkerSet set = map.getMarkerSets().computeIfAbsent(MARKERSET_ID, __ -> MarkerSet.builder() + .label(IntegrationsConfiguration.getConfiguration().dynmapSetName()) + .defaultHidden(false) + .toggleable(true) + .build()); + + POIMarker marker = POIMarker.builder() .label(quest.getName()) .icon(IntegrationsConfiguration.getConfiguration().dynmapMarkerIcon(), 0, 0) - .position(lc.getBlockX(), lc.getBlockY(), lc.getBlockZ()) + .position(lc.getX(), lc.getY(), lc.getZ()) .build(); - set.getMarkers().put("qu_" + quest.getId() + "_" + i++, marker); - map.getMarkerSets().putIfAbsent(MARKERSET_ID, set); + set.getMarkers().put("qu_" + quest.getId(), marker); } - QuestsPlugin.getPlugin().getLoggerExpanded().debug("Added " + i + " BlueMap markers for quest " + quest.getId()); + QuestsPlugin.getPlugin().getLoggerExpanded() + .debug("Added " + maps.size() + " BlueMap markers for quest " + quest.getId()); }); }); } - + @Override public void removeMarker(Quest quest) { BlueMapAPI.getInstance().ifPresent(api -> { Location lc = quest.getStarterNpc().getLocation(); api.getWorld(lc.getWorld()).map(BlueMapWorld::getMaps).ifPresent(maps -> { - for (int i = 0; i < maps.size(); i++) { - set.getMarkers().remove("qu_" + quest.getId() + "_" + i); + for (BlueMapMap map : maps) { + MarkerSet set = map.getMarkerSets().get(MARKERSET_ID); + if (set != null) + set.getMarkers().remove("qu_" + quest.getId()); } + QuestsPlugin.getPlugin().getLoggerExpanded() + .debug("Deleted " + maps.size() + " BlueMap markers for quest " + quest.getId()); }); }); } diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/BQLevelledMobs.java b/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/BQLevelledMobs.java index 682a3a5c..b4b0ecdd 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/BQLevelledMobs.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/BQLevelledMobs.java @@ -1,29 +1,35 @@ package fr.skytasul.quests.integrations.mobs; -import java.util.function.Consumer; -import org.bukkit.entity.Entity; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.bukkit.plugin.java.JavaPlugin; -import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.mobs.LeveledMobFactory; import fr.skytasul.quests.api.utils.MinecraftNames; import fr.skytasul.quests.api.utils.XMaterial; -import me.lokka30.levelledmobs.LevelledMobs; +import org.bukkit.Bukkit; +import org.bukkit.NamespacedKey; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.persistence.PersistentDataType; +import org.jetbrains.annotations.NotNull; +import java.util.function.Consumer; public class BQLevelledMobs implements LeveledMobFactory { + private final NamespacedKey levelKey; + + private final ItemStack item = ItemUtils.item(XMaterial.CHICKEN_SPAWN_EGG, "§eLevelledMobs"); + + public BQLevelledMobs() { + this.levelKey = new NamespacedKey(Bukkit.getPluginManager().getPlugin("LevelledMobs"), "level"); + } + @Override public String getID() { return "levelledMobs"; } - private ItemStack item = ItemUtils.item(XMaterial.CHICKEN_SPAWN_EGG, "§eLevelledMobs"); - @Override public ItemStack getFactoryItem() { return item; @@ -37,7 +43,10 @@ public void itemClick(Player p, Consumer run) { @Override public double getMobLevel(EntityType type, Entity entity) { - return JavaPlugin.getPlugin(LevelledMobs.class).levelInterface.getLevelOfMob((LivingEntity) entity); + Integer level = entity.getPersistentDataContainer().get(levelKey, PersistentDataType.INTEGER); + return level == null ? 0 : level.intValue(); + // return JavaPlugin.getPlugin(LevelledMobs.class).getLevelInterface().getLevelOfMob((LivingEntity) + // entity); } @Override diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/BQStackMob.java b/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/BQStackMob.java new file mode 100755 index 00000000..18f723e9 --- /dev/null +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/BQStackMob.java @@ -0,0 +1,40 @@ +package fr.skytasul.quests.integrations.mobs; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.mobs.MobStacker; +import org.bukkit.Bukkit; +import org.bukkit.entity.Entity; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.jetbrains.annotations.NotNull; +import uk.antiperson.stackmob.events.StackDeathEvent; +import java.util.concurrent.TimeUnit; + +public class BQStackMob implements Listener, MobStacker { + + private final Cache killedStacks = + CacheBuilder.newBuilder().expireAfterWrite(5, TimeUnit.SECONDS).build(); + + private BQStackMob() {} + + public static void initialize() { + BQStackMob stacker = new BQStackMob(); + QuestsAPI.getAPI().registerMobStacker(stacker); + Bukkit.getPluginManager().registerEvents(stacker, QuestsPlugin.getPlugin()); + } + + @EventHandler + public void onStackDeath(StackDeathEvent event) { + killedStacks.put(event.getStackEntity().getEntity().getEntityId(), event.getDeathStep()); + } + + @Override + public int getEntityStackSize(@NotNull Entity entity) { + Integer amount = killedStacks.getIfPresent(entity.getEntityId()); + return amount == null ? 1 : amount.intValue(); + } + +} diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/BQWildStacker.java b/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/BQWildStacker.java index 76f7458f..821aa55b 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/BQWildStacker.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/BQWildStacker.java @@ -1,12 +1,11 @@ package fr.skytasul.quests.integrations.mobs; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.event.Listener; import com.bgsoftware.wildstacker.api.WildStackerAPI; import fr.skytasul.quests.api.QuestsAPI; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; -public class BQWildStacker implements Listener { +public class BQWildStacker { private BQWildStacker() {} diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQFancyNPCs.java b/integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQFancyNPCs.java new file mode 100644 index 00000000..d33eeed3 --- /dev/null +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQFancyNPCs.java @@ -0,0 +1,114 @@ +package fr.skytasul.quests.integrations.npcs; + +import de.oliver.fancynpcs.api.FancyNpcsPlugin; +import de.oliver.fancynpcs.api.Npc; +import de.oliver.fancynpcs.api.NpcData; +import de.oliver.fancynpcs.api.events.NpcInteractEvent; +import fr.skytasul.quests.api.npcs.BqInternalNpc; +import fr.skytasul.quests.api.npcs.BqInternalNpcFactory.BqInternalNpcFactoryCreatable; +import fr.skytasul.quests.api.npcs.NpcClickType; +import org.bukkit.Location; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; +import java.util.stream.Collectors; + +public class BQFancyNPCs implements BqInternalNpcFactoryCreatable, Listener { + + @Override + public int getTimeToWaitForNPCs() { + return 105; + } + + @Override + public Collection getIDs() { + return FancyNpcsPlugin.get().getNpcManager().getAllNpcs().stream().map(npc -> npc.getData().getName()).collect(Collectors.toList()); + } + + @Override + public boolean isNPC(Entity entity) { + return false; + } + + @Override + public BqInternalNpc fetchNPC(String internalId) { + Npc npc = FancyNpcsPlugin.get().getNpcManager().getNpc(internalId); + return npc == null ? null : new BQFancyNpc(npc); + } + + @Override + public boolean isValidEntityType(EntityType type) { + return true; + } + + @Override + public @NotNull BqInternalNpc create(@NotNull Location location, @NotNull EntityType type, @NotNull String name, + @Nullable String skin) { + String id; + int i = 1; + while (FancyNpcsPlugin.get().getNpcManager().getNpc(id = name + "-" + i) != null) { + i++; + } + + NpcData npcData = new NpcData(id, null, location); + npcData.setType(type); + + + Npc npc = FancyNpcsPlugin.get().getNpcAdapter().apply(npcData); + FancyNpcsPlugin.get().getNpcManager().registerNpc(npc); + + return new BQFancyNpc(npc); + } + + @EventHandler + public void onInteract(NpcInteractEvent e) { + npcClicked(null, e.getNpc().getData().getName(), e.getPlayer(), + NpcClickType.of(e.getInteractionType() == NpcInteractEvent.InteractionType.LEFT_CLICK, e.getPlayer().isSneaking())); + } + + public static class BQFancyNpc implements BqInternalNpc { + + private final Npc npc; + + private BQFancyNpc(Npc npc) { + this.npc = npc; + } + + @Override + public String getInternalId() { + return npc.getData().getName(); + } + + @Override + public String getName() { + return npc.getData().getDisplayName(); + } + + @Override + public boolean isSpawned() { + return true; + } + + @Override + public Entity getEntity() { + return null; + } + + @Override + public Location getLocation() { + return npc.getData().getLocation(); + } + + @Override + public boolean setNavigationPaused(boolean paused) { + return true; + } + + } + +} \ No newline at end of file diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQMythicMobs5Npcs.java b/integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQMythicMobs5Npcs.java new file mode 100755 index 00000000..e6c29df6 --- /dev/null +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQMythicMobs5Npcs.java @@ -0,0 +1,136 @@ +package fr.skytasul.quests.integrations.npcs; + +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.npcs.BqInternalNpc; +import fr.skytasul.quests.api.npcs.BqInternalNpcFactory; +import fr.skytasul.quests.api.npcs.NpcClickType; +import io.lumine.mythic.api.mobs.MythicMob; +import io.lumine.mythic.bukkit.BukkitAdapter; +import io.lumine.mythic.bukkit.MythicBukkit; +import io.lumine.mythic.bukkit.events.MythicMobInteractEvent; +import io.lumine.mythic.bukkit.events.MythicReloadedEvent; +import io.lumine.mythic.core.mobs.ActiveMob; +import org.bukkit.Location; +import org.bukkit.entity.Entity; +import org.bukkit.event.*; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import java.util.Collection; +import java.util.Optional; + +public class BQMythicMobs5Npcs implements BqInternalNpcFactory, Listener { + + @Override + public int getTimeToWaitForNPCs() { + return 0; // TODO find accurate value + } + + @Override + public boolean isNPC(@NotNull Entity entity) { + return MythicBukkit.inst().getMobManager().isMythicMob(entity); + } + + @Override + public @NotNull Collection<@NotNull String> getIDs() { + return MythicBukkit.inst().getMobManager().getMobNames(); + } + + @Override + public @Nullable BqInternalNpc fetchNPC(String id) { + return MythicBukkit.inst().getMobManager().getMythicMob(id).map(BQMythicMobs5Npc::new).orElse(null); + } + + @EventHandler + public void onMythicInteract(MythicMobInteractEvent event) { + npcClicked(new MythicInteractEventProxy(event), event.getActiveMobType().getInternalName(), event.getPlayer(), + NpcClickType.RIGHT); + } + + @EventHandler + public void onMythicReloaded(MythicReloadedEvent event) { + npcsReloaded(); + } + + private class BQMythicMobs5Npc implements BqInternalNpc { + + private final @NotNull MythicMob mob; + + public BQMythicMobs5Npc(@NotNull MythicMob mob) { + this.mob = mob; + } + + @Override + public String getInternalId() { + return mob.getInternalName(); + } + + @Override + public @NotNull String getName() { + return mob.getDisplayName().get(); + } + + private @NotNull Optional getOneActiveMob() { + ActiveMob oneActiveMob = null; + for (ActiveMob activeMob : MythicBukkit.inst().getMobManager().getActiveMobs()) { + if (!activeMob.isDead() && activeMob.getType().equals(mob)) { + if (oneActiveMob == null) { + oneActiveMob = activeMob; + } else { + QuestsPlugin.getPlugin().getLogger() + .warning("Found two active mobs for the same Mythic Mobs NPC " + mob.getInternalName()); + break; + } + } + } + return Optional.ofNullable(oneActiveMob); + } + + @Override + public boolean isSpawned() { + return getOneActiveMob().isPresent(); + } + + @Override + public @Nullable Entity getEntity() { + return getOneActiveMob().map(mob -> mob.getEntity().getBukkitEntity()).orElse(null); + } + + @Override + public @NotNull Location getLocation() { + return getOneActiveMob().map(mob -> BukkitAdapter.adapt(mob.getLocation())).orElse(null); + } + + @Override + public boolean setNavigationPaused(boolean paused) { + return false; + } + + } + + private static class MythicInteractEventProxy extends Event implements Cancellable { + + private final @NotNull MythicMobInteractEvent event; + + public MythicInteractEventProxy(@NotNull MythicMobInteractEvent event) { + this.event = event; + } + + @Override + public boolean isCancelled() { + return event.isCancelled(); + } + + @Override + public void setCancelled(boolean cancel) { + if (cancel) + event.setCancelled(); + } + + @Override + public @NotNull HandlerList getHandlers() { + return null; + } + + } + +} diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/skillapi/SkillAPI.java b/integrations/src/main/java/fr/skytasul/quests/integrations/skillapi/SkillAPI.java deleted file mode 100644 index 71440af4..00000000 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/skillapi/SkillAPI.java +++ /dev/null @@ -1,30 +0,0 @@ -package fr.skytasul.quests.integrations.skillapi; - -import java.util.Collection; -import org.bukkit.entity.Player; -import com.sucy.skill.api.classes.RPGClass; -import com.sucy.skill.api.enums.ExpSource; - -public class SkillAPI { - - public static void giveExp(Player p, int xp){ - com.sucy.skill.SkillAPI.getPlayerData(p).giveExp(xp, ExpSource.QUEST); - } - - public static int getLevel(Player p) { - return com.sucy.skill.SkillAPI.getPlayerData(p).getMainClass().getLevel(); - } - - public static boolean classExists(String name){ - return getClass(name) != null; - } - - public static RPGClass getClass(String name) { - return com.sucy.skill.SkillAPI.getClass(name); - } - - public static Collection getClasses() { - return com.sucy.skill.SkillAPI.getClasses().values(); - } - -} diff --git a/pom.xml b/pom.xml index 10a0f2bd..4faa864a 100644 --- a/pom.xml +++ b/pom.xml @@ -42,10 +42,11 @@ 8 true unknown - 1.0.3 - 1.0.3 - + 1.0.4 + ${revision} + 1.20.6-R0.1-SNAPSHOT + @@ -87,6 +88,7 @@ v1_20_R2 v1_20_R3 v1_20_R4 + v1_21_R1 dist diff --git a/v1_21_R1/pom.xml b/v1_21_R1/pom.xml new file mode 100755 index 00000000..213c6983 --- /dev/null +++ b/v1_21_R1/pom.xml @@ -0,0 +1,83 @@ + + + 4.0.0 + jar + beautyquests-v1_21_R1 + + fr.skytasul + beautyquests-parent + ${revision} + + + + true + 1.21-R0.1-SNAPSHOT + 21 + ${java.version} + ${java.version} + ${java.version} + + + + + jitpack.io + https://jitpack.io + + + + + + fr.skytasul + beautyquests-core + ${revision} + provided + + + org.spigotmc + spigot + ${spigot.version} + remapped-mojang + provided + + + + + + + net.md-5 + specialsource-maven-plugin + 2.0.3 + + + package + + remap + + remap-obf + + org.spigotmc:minecraft-server:${spigot.version}:txt:maps-mojang + true + org.spigotmc:spigot:${spigot.version}:jar:remapped-mojang + true + remapped-obf + + + + package + + remap + + remap-spigot + + ${project.build.directory}/${project.artifactId}-${revision}-remapped-obf.jar + org.spigotmc:minecraft-server:${spigot.version}:csrg:maps-spigot + org.spigotmc:spigot:${spigot.version}:jar:remapped-obf + + + + + + + diff --git a/v1_21_R1/src/main/java/fr/skytasul/quests/utils/nms/v1_21_R1.java b/v1_21_R1/src/main/java/fr/skytasul/quests/utils/nms/v1_21_R1.java new file mode 100755 index 00000000..25345292 --- /dev/null +++ b/v1_21_R1/src/main/java/fr/skytasul/quests/utils/nms/v1_21_R1.java @@ -0,0 +1,49 @@ +package fr.skytasul.quests.utils.nms; + +import net.minecraft.core.Holder.Reference; +import net.minecraft.core.HolderLookup.RegistryLookup; +import net.minecraft.core.registries.Registries; +import net.minecraft.network.protocol.game.ClientboundOpenBookPacket; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.Property; +import org.bukkit.Material; +import org.bukkit.craftbukkit.v1_21_R1.entity.CraftPlayer; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import java.util.List; + +public class v1_21_R1 extends NMS{ + + @Override + public void openBookInHand(Player p) { + ClientboundOpenBookPacket packet = new ClientboundOpenBookPacket(InteractionHand.MAIN_HAND); + ((CraftPlayer) p).getHandle().connection.send(packet); + } + + @Override + public double entityNameplateHeight(Entity en) { + return en.getHeight(); + } + + @Override + public List getAvailableBlockProperties(Material material) { + RegistryLookup blockRegistry = MinecraftServer.getServer().registryAccess().lookupOrThrow(Registries.BLOCK); + Reference block = blockRegistry + .getOrThrow(ResourceKey.create(Registries.BLOCK, ResourceLocation.parse(material.getKey().toString()))); + StateDefinition stateList = block.value().getStateDefinition(); + return stateList.getProperties().stream().map(Property::getName).toList(); + } + + @Override + public List getAvailableBlockTags() { + return MinecraftServer.getServer().registryAccess().lookupOrThrow(Registries.BLOCK).listTags() + .map(x -> x.key().location().toString()).toList(); + } + +}