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 extends Number> 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();
+ }
+
+}